2017-04-16 184 views
0

我有這個C代碼是反彙編(AT & T),我有兩個東西混淆。首先,我的理解是EBP-4應該是堆棧中的第一個局部變量(這裏是int i)。我明確在EBP-8這裏。爲什麼是這樣?彙編局部變量和寄存器

其次,在對它們進行算術運算之前,是否需要將值移入寄存器? (這是一個x86 32位機)例如:

0x08048402 <+21>: mov 0x8(%ebp),%eax //move parameter a into eax 0x08048405 <+24>: add %eax,-0x4(%ebp) //r += a

爲什麼不能此是:

0x08048405 <+24>: add 0x8(%ebp),-0x4(%ebp) //r += a

的C代碼:

int loop_w (int a, int b){  
    int i = 0;  
    int r = a;  
    while (i < 256){   
     r += a;   
     a -= b;   
     i += b; 
    } 
return r; 

拆卸:

Dump of assembler code for function loop_w: 
    0x080483ed <+0>:  push %ebp 
    0x080483ee <+1>:  mov %esp,%ebp 
    0x080483f0 <+3>:  sub $0x10,%esp 
---------------Above is for stack setup----------------- 
    0x080483f3 <+6>:  movl $0x0,-0x8(%ebp)   //I=0 
    0x080483fa <+13>: mov 0x8(%ebp),%eax   //move parameter a into eax 
    0x080483fd <+16>: mov %eax,-0x4(%ebp)  //move a into local var (r=a) 
    0x08048400 <+19>: jmp 0x8048414 <loop_w+39> //start while loop 
    0x08048402 <+21>: mov 0x8(%ebp),%eax  //move parameter a into eax 
    0x08048405 <+24>: add %eax,-0x4(%ebp)  //r += a 
    0x08048408 <+27>: mov 0xc(%ebp),%eax  //move parameter b into eax 
    0x0804840b <+30>: sub %eax,0x8(%ebp)  //a += parameter b 
    0x0804840e <+33>: mov 0xc(%ebp),%eax  //move parameter b into eax 
    0x08048411 <+36>: add %eax,-0x8(%ebp)  //i+=b 
    0x08048414 <+39>: cmpl $0xff,-0x8(%ebp)   //compare i to 256 
    0x0804841b <+46>: jle 0x8048402 <loop_w+21> //continue loop if failed condition 
=> 0x0804841d <+48>: mov -0x4(%ebp),%eax  //move r into eax 
    0x08048420 <+51>: leave 
    0x08048421 <+52>: ret    //return eax 
End of assembler dump. 
+0

這一切都取決於編譯器是否在入口處或從堆棧分配後(後者更常見)分配堆棧起始處的變量。請注意,按照遞增的內存順序,我位於r之前(正常情況下)。 – user3344003

回答

2

編譯器可以決定要放置局部變量的任何位置。由於對齊的原因,它可能會將它放在%ebp-8。

第二個問題 - 變量是否必須在操作前加載到寄存器中,取決於操作和架構提供的指令集。

您提到過x86。對於這種體系結構尤其如此,X86不允許帶有兩個內存操作數的指令(是的,有一些例外)。

您可以搜索每個指令的基礎知道他們允許什麼樣的操作數。

+0

好的答案,簡潔明瞭。 –

+0

謝謝。我正在研究這個 - 所以如果我將彙編代碼寫入C代碼(在紙上),那麼說%ebp-4是「我」然後呢? – KenP

+0

是的,假設%ebp-4是i是錯誤的。您可能會想要查看生成的程序集並確定堆棧中每個變量的偏移量,但這不是可伸縮的,也不是可移植的。相反,你可以看看gcc和clang支持的擴展內聯彙編。它們允許您編寫變量名稱而不是偏移量,編譯器會爲您放置適當的地址(或註冊表)。 –