2014-10-09 10 views
7

मैं उपरोक्त सी कोड के संबंध में इस असेंबली कोड को समझने की कोशिश कर रहा हूं। मुझे यकीन नहीं है कि मैं सही रास्ते पर हूं तो शायद कोई मुझे इस पर बेहतर समझने में मदद कर सकता है।असेंबली भाषा को समझना

int silly(int n, int *p) 
{ 
    int val, val2; 
    if (n > 0) 
     val2 = silly(n << 1, &val); 
    else 
     val = val2 = 0; 
    *p = val + val2 + n; 
    return val + val2; 
} 

यह निम्न मशीन कोड पैदावार:

silly: 
pushl %ebp    // Here I am making space for the function on the stack 
movl %esp,%ebp   // Moving the stack pointer where the base pointer is 
subl $20,%esp   // Subtracting 20 from the stack pointer to allocate more space 
pushl %ebx    // Pushing the %ebx register on top of the stack 
movl 8(%ebp),%ebx  // Getting the first argument(which is n) and store it in register %ebx 
testl %ebx,%ebx  // The first if-statement which compares if n > 0 
jle .L3    // Jump if less or equal - meaning if n < 0 then jump to .L3 
addl $-8,%esp   // Add -8 to %esp to allocate more space 
leal -4(%ebp),%eax  // Storing the first local variable (which is val) in %eax 
pushl %eax    // Pushing the register %eax on top of the stack 
leal (%ebx,%ebx),%eax // n + n and stores it as 2n in %eax 
pushl %eax    // Pushing register %eax on top of the stack (Which I find strange 
         // considering that I've just pushed %eax onto the stack above 
call silly    // Call the function silly 
jmp .L4    // Jump to .L4 (Unconditionally) 
.p2align 4,,7   // Don't know what this means. 
.L3:     // .L3 is the else-statement 
xorl %eax,%eax   // Basically making %eax = 0 
movl %eax,-4(%ebp)  // Moving the value in %eax which is 0 to the first local variable 
         // meaning val = 0 
.L4:     // .L4 is the section after the else-statement 
movl -4(%ebp),%edx  // Getting val again and now storing it in %edx 
addl %eax,%edx   // Adding what is in %eax (which is 0) to %edx 
movl 12(%ebp),%eax  // Getting the second parameter (*p) and storing it in %eax 
addl %edx,%ebx   // Adding value from %edx to %ebx - meaning val + n 
movl %ebx,(%eax)  // Moving what is in %ebx and storing it in memory location of %eax 
movl -24(%ebp),%ebx // Getting the second local variable (val2) and moving it to %ebx 
movl %edx,%eax   // Move val to %eax - and the return value will be in %eax 
movl %ebp,%esp   
popl %ebp 
ret 

मैं इस के आसपास मेरे सिर लपेटो करने की कोशिश कर रहा हूँ और मैं सिर्फ विधानसभा के बारे में सोच तो इस विषय पर संकेत वास्तव में अच्छा होगा शुरू कर दिया है।

  • (एक) अलग-अलग वैल ढेर पर संग्रहीत है: मैं सवाल मैं इस विधानसभा कोड है जो ढेर की मेरी समझ में मदद कर सकता के बारे में पूछने की जरूरत है की एक जोड़ी है?
    (बी) यदि हां, तो क्या बाइट ओसेट (% ebp के सापेक्ष) पर यह संग्रहीत है?
    (सी) इसे ढेर पर स्टोर करना क्यों जरूरी है?

  • (ए) क्या वैरिएबल वैल 2 स्टैक पर संग्रहीत है?
    (बी) यदि हां, तो क्या बाइट ओसेट (% ebp के सापेक्ष) पर यह संग्रहीत है?
    (सी) इसे ढेर पर स्टोर करना क्यों जरूरी है?

  • (ए) क्या (यदि कुछ भी) -24 (% ईबीपी) पर संग्रहीत किया जाता है?
    (बी) अगर वहां कुछ संग्रहीत किया जाता है, तो इसे स्टोर करना क्यों आवश्यक है?

  • (ए) क्या (यदि कुछ भी) -8 (% ईबीपी) पर संग्रहीत किया जाता है?
    (बी) अगर वहां कुछ संग्रहीत किया जाता है, तो इसे स्टोर करना क्यों आवश्यक है?

अग्रिम :)

+4

आपका प्रश्न वास्तव में क्या है? – o11c

+0

मैंने अभी प्रश्न को अद्यतन किया है। क्षमा करें :) – drleifz

+0

नोट: 'val2' अनियंत्रित है। कभी-कभी। और कभी-कभी 'वाल' भी होता है। – wildplasser

उत्तर

1

अपने प्रश्नों के उत्तर देने से पहले। पर टिप्पणी करने के बजाय कोड कोड कर रहा है, मैं टिप्पणी करता हूं कि सभी मान रजिस्ट्रार या स्टैक पर हैं।

तर्क स्टैक पर हैं, वापसी मूल्य %eax में है।

रजिस्टर्स %eax, %ecx, और %edx कॉलर सहेजे गए हैं। %ebx, %ebp, और %esp समेत अन्य सभी रजिस्ट्रार, कैली-सेव किए गए हैं (%edi और %esi अप्रयुक्त हैं)।

स्टैक के लिए मेरा नोटेशन एक समय में 4 बाइट्स है और मैं ; का उपयोग करता हूं, जहां ईबीपी पॉइंट्स, यदि ज्ञात हैं।

silly:      ; eax: ?, ebx: ebx0, edx: ?, stack: [eip0, n, p] 
    pushl %ebp    ; eax: ?, ebx: ebx0, edx: ?, stack: [ebp0, eip0, n, p] 
    movl %esp,%ebp   ; eax: ?, ebx: ebx0, edx: ?, stack: [; ebp0, eip0, n, p] 
    subl $20,%esp   ; eax: ?, ebx: ebx0, edx: ?, stack: [?, ?, ?, ?, ?; ebp0, eip0, n, p] 
    pushl %ebx    ; eax: ?, ebx: ebx0, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] 
    movl 8(%ebp),%ebx  ; eax: ?, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] 
    testl %ebx,%ebx  ; set flags from n 
    jle .L3    ; if flags indicates <= 0, goto .L3, else fallthrough 

          ; set up for calling the function 
    addl $-8,%esp   ; eax: ?, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] 
    leal -4(%ebp),%eax  ; eax: &val, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, (stackeax); ebp0, eip0, n, p] 
    pushl %eax    ; eax: &val, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] 
    leal (%ebx,%ebx),%eax ; eax: 2*n, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] 
    pushl %eax    ; eax: 2*n, ebx: n, edx: ?, stack: [2*n, &val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] 
    call silly    ; pushes eip; args: (2*n, &val); val will be initialized on return 
    jmp .L4    ; 
          ; 
.p2align 4,,7    ; request alignment (there should be one before `silly:` too) 
.L3:      ; 
    xorl %eax,%eax   ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] 
    movl %eax,-4(%ebp)  ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
          ; 
.L4:      ; eax: val2=φ(function result, 0), ebx: n, edx: ?, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    movl -4(%ebp),%edx  ; eax: val2, ebx: n, edx: val, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    addl %eax,%edx   ; eax: val2, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    movl 12(%ebp),%eax  ; eax: p, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    addl %edx,%ebx   ; eax: p, ebx: n+val+val2, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    movl %ebx,(%eax)  ; *p = n+val+val2 
    movl -24(%ebp),%ebx ; eax: p, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    movl %edx,%eax   ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] 
    movl %ebp,%esp   ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [; ebp0, eip0, n, p] 
    popl %ebp    ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [eip0, n, p] 
    ret     ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [n, p] 

रोकें

वापस जाएं और कोड को फिर से पढ़ें। आप केवल खुद को चोट पहुंचा रहे हैं यदि आप अपने आप को जवाब नहीं समझते हैं। मैंने लिखी टिप्पणियों के साथ यह आसान होना चाहिए।

लेकिन वैसे भी ...


  1. एक। val आमतौर पर स्टैक पर -4(%ebp) पर होता है। यह एकमात्र समय नहीं है लाइन xorl %eax,%eax
    बी पर है। यह -4(%ebp) पर संग्रहीत है, जैसा कि leal -4(%ebp),%eax, movl %eax,-4(%ebp), और movl -4(%ebp),%edx लाइनों पर प्रमाणित है। इसके अतिरिक्त, पिछले फ्रेम का val*p
    सी है। val ढेर पर होना चाहिए ताकि उसका पता लिया जा सके और रिकर्सिव कॉल पर जा सके।
  2. ए। val2 स्टैक पर कभी भी संग्रहीत नहीं होता है, हालांकि अधिकतर ? एस उनमें से कुछ स्थान आरक्षित हैं।
    बी। यह पर .L4 पर रेजीक्सटर में संग्रहीत है, जो फ़ि फ़ंक्शन की पहली शाखा पर रिकर्सिव कॉल का रिटर्न वैल्यू है, और दूसरी शाखा पर 0 मान है, जिसे val में भी संग्रहीत किया गया था।
    सी। val2 अपने पते को नहीं लिया जाने के बाद कभी भी ढेर पर होने की जरूरत नहीं है, यह रिकर्सिव कॉल से पहले मौजूद नहीं है, इसलिए इसे सहेजने की आवश्यकता नहीं है, और उपयोग में कुछ पर्याप्त रजिस्ट्रार हैं जिन्हें स्पिल करने की आवश्यकता नहीं है।
  3. ए। -24(%ebp)%ebx का सहेजा गया मूल्य है, pushl %ebx
    बी से। %ebx एक कैली-सेव किया गया रजिस्टर है, इसलिए इसका मान संरक्षित होना चाहिए।
  4. ए। नहीं, वहां कुछ भी नहीं है।
    बी। यह संभवतः val2 होता है यदि इसे फैलाना आवश्यक था। मेरा सबसे अच्छा अनुमान यह है कि अन्य तीन ? एस अप्रयुक्त-के-द-द-रिकर्सिव-कॉल कॉलर-सहेजे गए रजिस्टरों के लिए आरक्षित हैं: %eax, %ecx, और %edx
0

धन्यवाद आप एक बहुत कहा है।

मैं इस हिस्से के साथ शुरू होगा ...

.p2align 4,,7 // Don't know what this means.

समझा; घबराहट, है ना!

प्रोग्रामर (आपके मामले में एक कंपाइलर जैसा दिखता है) L3: पर निर्देश चाहता है जिसे "16 बाइट सीमा" के नाम से जाना जाता है।

आप उस सामग्री के बारे में विवरण HERE पढ़ सकते हैं। अगर यह समझ में नहीं आता है, तो यहां वापस पूछें और मैं कुछ और समझाऊंगा।

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