簡體   English   中英

匯編語言如何運作?

[英]How an assembly language works?

我正在學習裝配,我有這個匯編代碼並且很難理解它可以有人澄清嗎?

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個字節,此reg從未再次使用,所以沒有任何意義做這個操作)。 現在將值0分配給由ebp小於8個字節的地址。

現在將該地址存儲到寄存器eax 現在將1添加到eax指向的值(前一個值丟失)。 現在將eax值存儲在[ebp-0x4] ,然后保留到main的返回地址。

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

int main(){

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

現在,有人可以弄清楚我的錯在哪里,而且我也不明白在<+13>的mov它將1添加到addrs ebp-0x8 ,但那是int x的地址所以, x不再包含0.我在哪里錯了?

首先, push ebp然后是mov 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 this instruction returns to the program, (it's slightly more
                                ; complicated than that)

希望這可以幫助! :)

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

設置堆棧框架。 保存舊的基指針並將堆棧的頂部設置為新的基指針。 這允許相對於ebp (基指針)引用此函數中的局部變量和參數。 這樣做的好處是它的值是穩定的,不像esp受pushpop的影響。

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

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

在這種情況下,堆棧擴展了16個字節。 在這種情況下,保留的空間比對齊目的所需的空間大:

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 )設置為此值。 返回地址通常在執行該函數的call指令之后直接保存指令的地址。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM