簡體   English   中英

理解一些匯編語句的目的

[英]Understanding the purpose of some assembly statements

我試圖了解一些匯編代碼並設法完成大部分匯編代碼,除了幾行。 我能夠理解大部分內部發生的事情,但我無法完全理解代碼開頭和結尾發生了什么(以及為什么會發生)。 有人可以對此有所了解嗎?

int main() {
    int a, b;
    a = 12;
    b = 20;
    b = a + 123;
    return 0;
}

拆卸版本:

 8048394:8d 4c 24 04          lea    0x4(%esp),%ecx              ; ??
 8048398:83 e4 f0             and    $0xfffffff0,%esp            ; ??
 804839b:ff 71 fc             pushl  -0x4(%ecx)                  ; ??
 804839e:55                   push   %ebp                        ; Store the Base pointer
 804839f:89 e5                mov    %esp,%ebp                   ; Initialize the Base pointer with the stack pointer
 80483a1:51                   push   %ecx                        ; ??
 80483a2:83 ec 4c             sub    $0x4c,%esp                  ; ??
 80483a5:c7 45 f8 0c 00 00 00 movl   $0xc,-0x8(%ebp)             ; Move 12 into -0x8(%ebp)
 80483ac:c7 45 f4 14 00 00 00 movl   $0x14,-0xc(%ebp)            ; Move 20 into -0xc(%ebp)
 80483b3:8b 45 f8             mov    -0x8(%ebp),%eax             ; Move 12@-0x8(%ebp) into eax
 80483b6:83 c0 7b             add    $0x7b,%eax                  ; Add 123 to 12@eax
 80483b9:89 45 f4             mov    %eax,-0xc(%ebp)             ; Store the result into b@-0xc(%ebp)
 80483bc:b8 00 00 00 00       mov    $0x0,%eax                   ; Move 0 into eax
 80483c1:83 c4 10             add    $0x10,%esp                  ; ??
 80483c4:59                   pop    %ecx                        ; ??
 80483c5:5d                   pop    %ebp                        ; ??
 80483c6:8d 61 fc             lea    -0x4(%ecx),%esp             ; ??

堆棧向下增長。 push從堆棧指針(esp)中減去,並且pop添加到esp。 你必須牢記這一點,以了解很多這一點。

8048394:8d 4c 24 04          lea    0x4(%esp),%ecx              ; ??

lea =加載有效地址

這將4字節的東西的地址保存到堆棧中。 由於這是32位(4字節字)x86代碼,這意味着堆棧中的第二項。 由於這是函數的代碼(在這種情況下為main),因此堆棧頂部的4個字節是返回地址。

8048398:83 e4 f0             and    $0xfffffff0,%esp            ; ??

此代碼確保堆棧對齊到16個字節。 在此操作之后,esp將小於或等於此操作之前的值,因此堆棧可能會增長,從而保護可能已存在於堆棧中的任何內容。 這有時在main中完成,以防函數使用未對齊的堆棧調用,這會導致事情變得非常慢(我認為16字節是x86上的緩存行寬,盡管4字節對齊在這里非常重要)。 如果main有一個未對齊的堆棧,那么程序的其余部分也將如此。

 804839b:ff 71 fc             pushl  -0x4(%ecx)                  ; ??

由於ecx之前被加載為指向前一個堆棧頂部返回地址另一側的東西的指針,所以因為它有一個-4索引,這指的是返回當前函數被推回的返回地址到堆棧的頂部,以便main可以正常返回。 (推送是神奇的,似乎能夠在同一指令中加載和存儲到RAM中的不同位置)。

 804839e:55                   push   %ebp                        ; Store the Base pointer
 804839f:89 e5                mov    %esp,%ebp                   ; Initialize the Base pointer with the stack pointer
 80483a1:51                   push   %ecx                        ; ??
 80483a2:83 ec 4c             sub    $0x4c,%esp                  ; ??

這主要是標准的功能序言(以前的東西是主要的特殊功能)。 這是一個堆棧框架(ebp和esp之間的區域),其中局部變量可以存在。 推送ebp,以便可以在結尾(在當前函數的末尾)恢復舊的堆棧幀。

80483a5:c7 45 f8 0c 00 00 00 movl   $0xc,-0x8(%ebp)             ; Move 12 into -0x8(%ebp)
80483ac:c7 45 f4 14 00 00 00 movl   $0x14,-0xc(%ebp)            ; Move 20 into -0xc(%ebp)
80483b3:8b 45 f8             mov    -0x8(%ebp),%eax             ; Move 12@-0x8(%ebp) into eax
80483b6:83 c0 7b             add    $0x7b,%eax                  ; Add 123 to 12@eax
80483b9:89 45 f4             mov    %eax,-0xc(%ebp)             ; Store the result into b@-0xc(%ebp)

80483bc:b8 00 00 00 00       mov    $0x0,%eax                   ; Move 0 into eax

eax是存儲整數函數返回值的地方。 這是設置為從main返回0。

80483c1:83 c4 10             add    $0x10,%esp                  ; ??
80483c4:59                   pop    %ecx                        ; ??
80483c5:5d                   pop    %ebp                        ; ??
80483c6:8d 61 fc             lea    -0x4(%ecx),%esp             ; ??

這是功能結局。 由於開頭的奇怪堆棧對齊代碼,因此更難理解。 盡管如此,我在弄清楚為什么堆棧的調整次數比次數更少時會有一點麻煩。

很明顯,這個特定的代碼沒有使用優化編譯。 如果那里可能不會那么多,因為編譯器可以看到,即使它沒有在你的main列出的數學,程序的最終結果是相同的。 對於實際執行某些操作(具有副作用或結果)的程序,有時更容易閱讀輕微優化的代碼(-cc或-0s參數到gcc)。

對於非main函數,由編譯器生成的讀取匯編通常更容易。 如果你想閱讀以理解代碼,那么你自己寫一個函數,它接受一些參數來產生一個結果或者對全局變量起作用,你將能夠更好地理解它。

可能對你有幫助的另一件事就是讓gcc為你生成匯編文件,而不是反匯編它們。 -S標志告訴它生成它(但不生成其他文件),並在末尾用.s命名匯編文件。 這比閱讀反匯編版本更容易閱讀。

不知道為什么編譯器會完成所有這些工作,但這就是我能解讀的內容:

 8048394:8d 4c 24 04          lea    0x4(%esp),%ecx              ; ecx := esp+4
 8048398:83 e4 f0             and    $0xfffffff0,%esp            ; align the stack to 16 bytes
 804839b:ff 71 fc             pushl  -0x4(%ecx)                  ; push [ecx-4] ([esp])
 80483a1:51                   push   %ecx                        ; push ecx
 80483a2:83 ec 4c             sub    $0x4c,%esp                  ; allocate 19 dwords on stack
 80483c1:83 c4 10             add    $0x10,%esp                  ; deallocate 4 dwords from stack
 80483c4:59                   pop    %ecx                        ; restore ecx
 80483c5:5d                   pop    %ebp                        ; and ebp
 80483c6:8d 61 fc             lea    -0x4(%ecx),%esp             ; esp := [ecx-4]

暫無
暫無

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

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