[英]What is the use of “push %ebp; movl %esp, %ebp” generated by GCC for x86?
這兩條指令在gcc為x86機器生成的匯編代碼中產生了什么影響:
push %ebp
movl %esp, %ebp
unwind的解釋是字面上的事實(盡管有一個較小的方向性錯誤),但沒有解釋原因。
%ebp
是您的堆棧框架的“基本指針”。 它是C運行時用來訪問堆棧上的局部變量和參數的指針。 這是GCC生成的一些典型的函數序言代碼(准確地說是g ++),首先是C ++源代碼。
// junk.c++
int addtwo(int a)
{
int x = 2;
return a + x;
}
這將生成以下匯編程序。
.file "junk.c++"
.text
.globl _Z6addtwoi
.type _Z6addtwoi, @function
_Z6addtwoi:
.LFB2:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $16, %esp
.LCFI2:
movl $2, -4(%ebp)
movl -4(%ebp), %edx
movl 8(%ebp), %eax
addl %edx, %eax
leave
ret
.LFE2:
.size _Z6addtwoi, .-_Z6addtwoi
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
現在解釋一下序言代碼( .LCFI2:
之前的所有內容),首先:
pushl %ebp
將調用函數的堆棧幀存儲在堆棧中。 movl %esp, %ebp
獲取當前的堆棧指針,並將其用作被調用函數的框架。 subl $16, %esp
為局部變量留出空間。 現在,您的功能已准備就緒,可以開始業務了。 與%ebp%
寄存器的偏移量為負的任何引用都是您的局部變量(在本示例中為x
)。 任何從%ebp%
寄存器偏移正值的引用都是您傳入的參數。
最后的關注點是leave
指令,它是x86匯編程序指令,它負責恢復調用函數的堆棧幀。 通常,這可以優化為在C代碼中更快地move %ebp %esp
和pop %ebp%
序列。 但是,出於說明目的,我根本沒有進行任何優化。
這是在函數開始時看到的典型代碼。
它將EBP寄存器的內容保存在堆棧中,然后將當前堆棧指針的內容存儲在EBP中。
在函數調用期間使用堆棧來存儲局部參數。 但是在函數中,堆棧指針可能會更改,因為值存儲在堆棧中。
如果保存堆棧的原始值,則可以通過EBP寄存器引用存儲的參數,而您仍然可以使用堆棧(向堆棧中添加值)。
在函數的最后,您可能會看到命令
pop %ebp ; restore original value
ret ; return
push %ebp
這會將32位(擴展的)基本指針寄存器壓入堆棧,即堆棧指針(%esp)減四,然后將%ebp的值復制到堆棧指針指向的位置。
movl %esp, %ebp
這會將堆棧指針寄存器復制到基本指針寄存器。
將堆棧指針復制到基本指針的目的是創建一個堆棧框架,即堆棧上子程序可以存儲本地數據的區域。 子例程中的代碼將使用基本指針來引用數據。
它是所謂的函數prolog的一部分 。
它保存函數結束時要檢索的當前基本指針,並將新的ebp設置為新幀的開頭。
我還認為必須注意的是,通常在push %ebp
和movl %esp, %ebp
,程序集push %ebx
或push %edx
。 這些是寄存器%ebx
和%edx
調用者保存。 在例行調用結束時,寄存器將恢復為其原始值。
另外- %ebx, %esi, %edi
都是被調用者保存寄存器。 因此,如果要覆蓋它們,則需要先保存它們,然后再還原它們。
這段代碼為您的程序設置了堆棧。
在x86堆棧中,信息由兩個寄存器保存。
Base pointer (bp): Holds starting address of the stack
Stack pointer (sp): Holds the address in which next value will be stored
這些寄存器在不同模式下具有不同的名稱:
Base pointer Stack pointer
16 bit real mode: bp sp
32 bit protected mode: ebp(%ebp) esp(%esp)
64 bit mode: rbp rsp
設置堆棧時,堆棧指針和基址指針在開始時會獲得相同的地址。
現在解釋一下您的代碼,
push %ebp
此代碼將當前堆棧地址壓入堆棧,以便函數可以正確“退出”或“返回”。
movl %esp, %ebp
這段代碼為您的函數設置了堆棧。
有關更多信息,請參閱此問題 。
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.