[英]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受push
和pop
的影響。
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.