2013-11-25 63 views
2

我正在學習大會,我有這個彙編代碼,並有很多理解它有人可以澄清它嗎?彙編語言如何工作?

Dump of assembler code for function main: 
0x080483ed <+0>: push ebp 
0x080483ee <+1>: mov ebp,esp 
0x080483f0 <+3>: sub esp,0x10 
0x080483f3 <+6>: mov DWORD PTR [ebp-0x8],0x0 
0x080483fa <+13>: mov eax,DWORD PTR [ebp-0x8] 
0x080483fd <+16>: add eax,0x1 
0x08048400 <+19>: mov DWORD PTR [ebp-0x4],eax 
0x08048403 <+22>: leave 
0x08048404 <+23>: ret 

到現在爲止,我的理解知識是:

推的東西(不知道是什麼)在ebp寄存器。然後將esp寄存器的內容轉換爲ebp(我認爲ebp的數據應該被覆蓋),然後從esp中減去10並將它存儲在esp(該函數將佔用10個字節,該寄存器不再被使用,所以沒有點做這個操作)。現在將值0指定爲小於ebp的8個字節指向的地址。

現在將該地址存儲到寄存器eax。現在,將eax指向的值加1(以前的值丟失)。現在將eax的值存儲在[ebp-0x4]上,然後轉到main的返回地址。

這裏是上面的程序我的C代碼:

int main(){ 

int x=0; 
int y = x+1; 
} 

現在,有人可以計算出,如果我沒猜錯的話,我也不懂mov在< +13>它增加了1加到地址ebp-0x8,但那是int x的地址所以,x不再包含0.我在哪裏錯了?

+3

爲什麼不選擇裝配教程? 'push ebp'不會將某些東西壓入'ebp',它會將當前的'ebp'內容壓入堆棧,以便稍後恢復。 – user4815162342

+0

閱讀下面的內容:http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames – Rob

回答

9

首先,push ebpmov ebp, esp是在過程開始時常見的兩條指令。 ESP寄存器是堆棧頂部的一個指示器 - 因此它隨着堆棧的增長或收縮而不斷變化。 EBP在這裏是一個幫助註冊。首先,我們在堆棧上推送ebp的內容。那麼我們將ESP(當前棧頂地址)複製到ebp - 這就是爲什麼當我們引用堆棧中的其他項時,我們使用ebp的常量值(而不是改變esp中的一個)。

sub esp, 0x10 ; means we reserve 16 bytes on the stack (0x10 is 16 in hex) 
現在

了真正的樂趣:

mov DWORD PTR [ebp-0x8],0x0 ; remember ebp was showing on the stack 
           ; top BEFORE reserving 16 bytes. 
           ; DWORD PTR means Double-word property which is 32 bits. 
           ; so the whole instruction means 
           ; "move 0 to the 32 bits of the stack in a place which 
           ; starts with the adress ebp-8. 
           ; this is our`int x = 0` 

mov eax,DWORD PTR [ebp-0x8] ; send x to EAX register. 
add eax,0x1`    ; add 1 to the eax register 
mov DWORD PTR [ebp-0x4],eax ; send the result (which is in eax) to the stack adress 
           ; [ebp-4] 
leave       ; Cleanup stack (reverse the "mov ebp, esp" from above). 
ret       ; let's say they return to the program, (it's slightly more 
           ; complicated than that) 

希望這有助於! :)

+0

'(0x10是十六進制中的32)'你確定嗎? –

+0

這裏有兩個問題,'sub esp,0x10'的利潤是什麼,這個命令既不做任何事也不需要它,第二個問題是,寄存器不包含地址。它也可以包含值?像'add eax,0x1'一樣? –

+0

我認爲它的十進制數爲17 ... –

2
0x080483ed <+0>: push ebp 
0x080483ee <+1>: mov ebp,esp 

設置堆棧幀。保存舊的基本指針並將堆棧頂部設置爲新的基本指針。這允許本函數中的局部變量和參數相對於ebp(基址指針)被引用。這樣做的好處是它的價值是穩定的,不像esp,它受push es和pop s的影響。

0x080483f0 <+3>: sub esp,0x10 

在x86平臺上的棧 '增長' 向下。一般來說,這意味着esp具有比ebp更低的值(內存中的地址)。當ebp == esp堆棧沒有爲局部變量保留任何內存時。這並不意味着它是'空' - 例如,一個堆棧的常見用法是[ebp+0x8]。在這種情況下,代碼正在尋找在調用之前先前被推入的堆棧中的東西(這可能是stdcall慣例中的參數)。

在這種情況下,堆棧擴展了16個字節。在這種情況下更多的空間比需要保留用於alignment用途:

0x080483f3 <+6>: mov DWORD PTR [ebp-0x8],0x0 

[ebp-0x8]的4個字節被初始化爲值0。這是您的x局部變量。

0x080483fa <+13>: mov eax,DWORD PTR [ebp-0x8] 

[ebp-0x8]的4個字節被移動到一個寄存器。算術操作碼不能用兩個內存操作數進行操作。在算術執行之前,數據需要先移到寄存器。 eax現在保存您的x變量的值。

0x080483fd <+16>: add eax,0x1 

eax值增加,使得它現在持有的價值x + 1

0x08048400 <+19>: mov DWORD PTR [ebp-0x4],eax 

將計算值存回堆棧。注意局部變量現在是[ebp-0x4] - 這是你的y變量。

0x08048403 <+22>: leave 

銷燬堆棧幀。基本上映射到pop ebp並恢復舊的堆棧基址指針。

0x08048404 <+23>: ret 

彈出堆棧處理的值作爲返回地址的頂部,並設置程序指針(eip),以該值。返回地址通常保存指令的地址,該指令直接在執行該函數的指令後執行。