“有什么用?”;按%ebp;移动百分比esp,%ebp“;由GCC为x86生成?
这两条指令对gcc为x86机器生成的汇编代码有什么影响:“有什么用?”;按%ebp;移动百分比esp,%ebp“;由GCC为x86生成?,gcc,assembly,x86,Gcc,Assembly,X86,这两条指令对gcc为x86机器生成的汇编代码有什么影响: push %ebp movl %esp, %ebp 这是在函数开头看到的典型代码 它将EBP寄存器的内容保存在堆栈上,然后将当前堆栈指针的内容存储在EBP中 堆栈在函数调用期间用于存储本地参数。但在函数中,堆栈指针可能会更改,因为值存储在堆栈上 如果保存堆栈的原始值,则可以通过EBP寄存器引用存储的参数,同时仍然可以使用(向堆栈添加值) 在函数的末尾,您可能会看到命令 pop %ebp ; restore original valu
push %ebp
movl %esp, %ebp
这是在函数开头看到的典型代码 它将EBP寄存器的内容保存在堆栈上,然后将当前堆栈指针的内容存储在EBP中 堆栈在函数调用期间用于存储本地参数。但在函数中,堆栈指针可能会更改,因为值存储在堆栈上 如果保存堆栈的原始值,则可以通过EBP寄存器引用存储的参数,同时仍然可以使用(向堆栈添加值) 在函数的末尾,您可能会看到命令
pop %ebp ; restore original value
ret ; return
这是我们所知的 它保存函数结束时将要检索的当前基指针,并将新ebp设置为新帧的开头
push %ebp
这将推动堆栈上的32位(扩展)基指针寄存器,即堆栈指针(%esp)减去四,然后将%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代码中以更快的移动%ebp%esp
和pop%ebp%
顺序进行优化。然而,出于说明目的,我根本没有在编译时进行任何优化。我还认为在编译之后经常注意这一点很重要
推送%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
此代码为函数设置堆栈。
有关更多信息,请参阅此。
希望这有帮助 除此之外,还有各种调用约定,用于控制将输入参数推送到堆栈上的顺序,以及在函数完成后谁将进行清理。movl%ebp,%esp/popl%ebp/ret
-->首先还原esp
,然后弹出ebp
前面没有描述最后一句话。谢谢你!向上投票。