2011-05-02 19 views
13

मैं पढ़ रहा था असेंबली भाषा की कला (रैंडल हाइड, link to Amazon) और मैंने उस पुस्तक में एक कंसोल एप्लिकेशन की कोशिश की। यह एक ऐसा प्रोग्राम था जिसने Win32 API फ़ंक्शंस का उपयोग करके स्वयं के लिए एक नया कंसोल बनाया था। कार्यक्रम में LENSTR नामक एक प्रक्रिया शामिल है, जो EBP रजिस्टर में स्ट्रिंग की लंबाई संग्रहीत करती है।असेंबली में प्रवेश करें और छोड़ दें?

LENSTR PROC 
ENTER 0, 0 
PUSH EAX 
;---------------------- 
CLD 
MOV EDI, DWORD PTR [EBP+08H] 
MOV EBX, EDI 
MOV ECX, 100 ; Limit the string length 
XOR AL, AL 
REPNE SCASB ; Find the 0 character 
SUB EDI, EBX ; String length including 0 
MOV EBX, EDI 

DEC EBX 
;---------------------- 
POP EAX 
LEAVE 
RET 4 
LENSTR ENDP 

आप enter और leave आदेशों यहाँ के उपयोग समझा सकते हैं: इस कार्य के लिए कोड इस प्रकार है?

उत्तर

12

यह फ़ंक्शन के लिए स्टैक फ्रेम (सक्रियण रिकॉर्ड) के लिए सेटअप है। आंतरिक रूप से यह आम तौर पर इस तरह दिखता है:

push(ebp);   // Save a copy of the old EBP value 

mov(esp, ebp);  // Get ptr to base of activation record into EBP 

sub(NumVars, esp); // Allocate storage for local variables. 

फिर जब स्टैक फ्रेम फिर से नष्ट कर दिया जा रहा है, तो आपको निम्न पंक्तियों के साथ कुछ करने के लिए:

mov(ebp, esp); // Deallocate locals and clean up stack. 

    pop(ebp);   // Restore pointer to caller's activation record. 

    ret();    // Return to the caller. 

Here इसके बारे में एक बेहतर व्याख्या है एचएलए का उपयोग करना यद्यपि यह उस पुस्तक में अच्छी तरह से समझाया गया है जिसे आप पढ़ रहे हैं, क्योंकि मेरे पास यह पुस्तक भी है, और मैंने इसे समझाते हुए अनुभाग को पढ़ा है।

+3

नहीं hla ...; ( – BlackBear

+0

[यह] (http://x86.renejeschke.de/html/file_module_x86_id_154.html) और [यह] (http://x86.renejeschke.de/html/file_module_x86_id_78.html) और अधिक सही हो सकता है। – lzutao

0

केवल स्टैक फ्रेम को दर्ज करें और छोड़ दें। आम तौर पर कंपाइलर्स कोड उत्पन्न करते हैं जो सीधे स्टैक फ्रेम पॉइंटर्स को एंटरप्राइज़ करते हैं और छोड़ते हैं जैसे mov/sub (वे 286 दिनों में वापस आते हैं :-)) के साथ बिल्कुल तेज़ नहीं होते हैं।

+0

नहीं - वे कभी तेज नहीं थे, बस अधिक कॉम्पैक्ट और बहुमुखी (वे पास्कल-शैली नेस्टेड फ़ंक्शंस का समर्थन करते हैं)। –

+2

दिलचस्प बात यह है कि एमएएसएम 32 (जब स्थानीय चर नियोजित होते हैं) पुश/एमओवी/एडीडी के साथ प्रवेश भाग करता है, लेकिन उन्हें छुट्टी के साथ नष्ट कर देता है ... –

+5

सही: 'एंटर' ने नेस्टेड फ़ंक्शंस का समर्थन करने के लिए ओवरहेड किया है, भले ही आप उपयोग न करें उन्हें। 'छोड़ें' कोई ओवरहेड नहीं जोड़ता है, और बराबर mov/pop से थोड़ा छोटा है। –

34

Enter एक स्टैक फ्रेम बनाता है, और leave एक स्टैक फ्रेम को नष्ट कर देता है। enter पर 0,0 मानकों के साथ, वे मूल रूप से के बराबर कर रहे हैं:

; enter 
push ebp 
mov ebp, esp 

; leave 
mov esp, ebp 
pop ebp 

हालांकि यह कोड आप पोस्ट में इस्तेमाल नहीं कर रहा है, enter थोड़ा सरल धक्का/mov ऊपर दिखाए गए संयोजन की तुलना में अधिक कर का समर्थन करता है। enter का पहला पैरामीटर स्थानीय चर के लिए आवंटित करने के लिए पर्याप्त मात्रा निर्दिष्ट करता है।

push ebp 
mov ebp, esp 
sub esp, 5 

Enter भी पास्कल जैसी भाषाओं नेस्टेड कार्य/प्रक्रियाओं का उपयोग कर सकते है कि समर्थन करता है: उदाहरण के लिए, enter 5, 0 मोटे तौर पर के बराबर है

procedure X; 
    procedure Y; 
    begin 
     { ... } 
    end 
begin 
    { ... } 
end 

इस तरह के मामले में, Y न केवल की पहुंच है इसके अपने स्थानीय चर, लेकिन सभी चर के लिए स्थानीय X पर भी। इन्हें मनमानी गहराई के लिए घोंसला दिया जा सकता है, इसलिए आपके पास ZY के अंदर हो सकता है जिसके पास अपने स्थानीय चर, और Y के चर और X के चर शामिल थे। enter को दूसरा पैरामीटर नेस्टिंग गहराई निर्दिष्ट करता है, तो X का उपयोग enter Sx, 0, Yenter Sy, 1 का प्रयोग करेंगे होगा और Zenter Sz, 2 का प्रयोग करेंगे (जहां Sx, Sy और Sz क्रमशः X, Y और Z को स्थानीय चर के आकार को दर्शाता है)।

यह ZY और X पर स्थानीय चर के उपयोग के लिए स्टैक फ्रेम की एक श्रृंखला बनाएगा, और इसी तरह। यदि कार्य रिकर्सिव हैं, तो यह काफी गैर-तुच्छ हो जाता है, इसलिए Z का आविष्कार केवल दो सबसे हालिया ढेर फ्रेमों तक ढेर नहीं चला सकता है - इसे अपने पिछले इनवॉशंस से स्टैक फ्रेम में छोड़ने की ज़रूरत है, और सीधे जाएं वापस लेक्सिकल पैरेंट फ़ंक्शन/प्रक्रिया के लिए फ़्रेम ढेर करने के लिए, जो रिकर्सन के मामले में अपने कॉलर से अलग है।

यह जटिलता भी है क्योंकि सी और सी ++ नेस्टेड कार्यों को प्रतिबंधित करते हैं। प्रवेश/छुट्टी की उपस्थिति को देखते हुए, वे इंटेल प्रोसेसर पर समर्थन करने के लिए काफी आसान हैं, लेकिन ऐसे कई प्रोसेसर पर काफी कठिन हो सकते हैं जिनमें ऐसे प्रत्यक्ष समर्थन की कमी है।

यह कम से कम एक दूसरे को समझाने में मदद करता है ...enter की सुविधा - यहां उपयोग किए जाने वाले मामूली मामले के लिए (यानी, enter 0, 0) यह push/mov का उपयोग कर समतुल्य से थोड़ा धीमा है।

+0

तो क्या वे मैक्रोज़ हैं ..? – BlackBear

+3

@ ब्लैकबियर: नहीं, वे निर्देश हैं, लेकिन वे "शॉर्टेंड" निर्देशों के प्रकार हैं - आप उन्हें बिना पूरा कर सकते हैं। –

+0

ठीक है इसे मिला :) (चार सीमा) – BlackBear

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