2016-02-14 4 views
5

मैं असेंबली के लिए बहुत नया हूं और नीचे दिया गया कोड दो अलग-अलग कार्यों के माध्यम से दो पूर्णांक को स्वैप करना है: पहले swap_c का उपयोग करके और फिर swap_asm का उपयोग करना।रजिस्ट्रार को दबाकर यह स्वैप w/o कितना सुरक्षित है?

हालांकि, मुझे शक है, कि क्या मैं push (मैं बचाने मतलब) से (बस main पर लौटने से पहले) विधानसभा कोड और बाद में pop उन्हें पहले रजिस्टरों के प्रत्येक मान की जरूरत है। दूसरे शब्दों में, सीपीयू मुझ पर पागल हो जाएगा अगर मैं अलग रजिस्टर सामग्री (नहीं ebp या esp की तरह महत्वपूर्ण लोगों, लेकिन, सिर्फ eax, ebx, ecx & edx) लौट swap_asm समारोह चलाने के बाद? असेंबली भाग में लाइनों को कम करना बेहतर है?

यह कोड मेरे लिए ठीक चलाता है और मैं असेंबल C कोड की 27 लाइनों को 7 असेंबली लाइनों तक कम करने में कामयाब रहा।

पीएस .: सिस्टम विंडोज 10, वीएस -2013 एक्सप्रेस है।

main.c हिस्सा

#include <stdio.h> 

extern void swap_asm(int *x, int *y); 

void swap_c(int *a, int *b) { 
    int t = *a; 
    *a = *b; 
    *b = t; 
} 

int main(int argc, char *argv[]) { 
    int x = 3, y = 5; 
    printf("before swap => x = %d  y = %d\n\n", x, y); 

    swap_c(&x, &y); 
    printf("after swap_c => x = %d  y = %d\n\n", x, y); 

    swap_asm(&x, &y); 
    printf("after swap_asm => x = %d  y = %d\n\n", x, y); 

    getchar(); 
    return (0); 
} 

assembly.asm हिस्सा

.686 
.model flat, c 
.stack 100h 
.data 

.code 
swap_asm proc 
    ; push eax 
    ; push ebx 
    ; push ecx 
    ; push edx 
    mov eax, [esp] + 4 ; get address of "x" stored in stack into eax 
    mov ebx, [esp] + 8 ; get address of "y" stored in stack into ebx 
    mov ecx, [eax]  ; get value of "x" from address stored in [eax] into ecx 
    mov edx, [ebx]  ; get value of "y" from address stored in [ebx] into edx 
    mov [eax], edx  ; store value in edx into address stored in [eax] 
    mov [ebx], ecx  ; store value in ecx into address stored in [ebx] 
    ; pop edx 
    ; pop ecx 
    ; pop ebx 
    ; pop eax 
    ret 
swap_asm endp 
end 
+2

आप समर्पित [ 'xchg'] (http://x86.renejeschke.de/html/file_module_x86_id_328.html) अनुदेश – anatolyg

+0

उपयोग कर सकते हैं अगर आप परमाणु जरूरत है तो एक स्मृति संकार्य प्रस्तुत किया जाने के साथ' xchg' @anatolyg परमाणु – user3528438

+1

का उपयोग बस लॉक जो कुछ ऐसा है जो आप शायद नहीं चाहते हैं। – fuz

उत्तर

8

आम तौर पर, इस प्रणाली आप पर काम कर रहे हैं बुला सम्मेलन पर निर्भर करता है। कॉलिंग सम्मेलन निर्दिष्ट करता है कि कार्यों को कैसे कॉल करें। आम तौर पर, यह कहता है कि तर्क कहां रखना है और किस रजिस्ट्रार को बुलाए गए फ़ंक्शन द्वारा संरक्षित किया जाना चाहिए।

cdecl बुला सम्मेलन के साथ i386 विंडोज (जो आपके द्वारा शायद का उपयोग करें) पर, आप स्वतंत्र रूप से eax, ecx, और edx रजिस्टरों के ऊपर लिख सकते हैं। ebx रजिस्टर संरक्षित किया जाना चाहिए। जबकि आपका कोड काम पर प्रतीत होता है, यह रहस्यमय रूप से असफल हो जाता है जब कोई फ़ंक्शन ebx पर संरक्षित होने पर निर्भर करता है, इसलिए बेहतर सहेजें और इसे पुनर्स्थापित करें।

+0

मुझे पता है कि 'swap_asm' को कॉल करने से पहले मुझे 'ecx' को धक्का देना होगा, अगर एक लूप के भीतर' swap_asm' कहा जाता है; लेकिन मुझे 'ebx' का कारण नहीं मिला। क्या आप इसे थोड़ा समझा सकते हैं? अग्रिम में धन्यवाद। – ssd

+1

@ merkez3110 रजिस्टर्स को फ़ंक्शन कॉल के संबंध में दो वर्गों में समूहीकृत किया जाता है: * कॉलर सहेजे गए रजिस्टर्स * जैसे 'ecx' को कॉलर द्वारा संरक्षित किया जाना चाहिए यदि कॉलर उन्हें संरक्षित करना चाहता है और कैली द्वारा स्वतंत्र रूप से ओवरराइट किया जा सकता है। * कैली बचाए गए रजिस्ट्रार * जैसे 'ईबीएक्स' को कैली द्वारा संरक्षित किया जाना चाहिए, कॉलर यह मान सकता है कि फ़ंक्शन कॉल के बाद रजिस्टर के समान मूल्य है। क्या इससे आपके प्रश्न का उत्तर मिलता है? – fuz

+1

जो मैंने अभी तक प्राप्त किया है: (1) 'ecx' ** कॉलर सहेजा गया ** है; ओवरराइट करने के लिए स्वतंत्र महसूस करें; (2) 'ईबीएक्स' ** कैली सहेजा गया ** है; कॉलर से प्राप्त मूल मूल्य वापस करना बेहतर है। फिर से धन्यवाद। – ssd

संबंधित मुद्दे