nar*_*tra 1 linux assembly gdb
我刚刚开始学习装配.这是来自gdb的转储,用于打印hello ranjit的简单程序.
Dump of assembler code for function main:
0x080483b4 <+0>: push %ebp
0x080483b5 <+1>: mov %esp,%ebp
0x080483b7 <+3>: sub $0x4,%esp
=> 0x080483ba <+6>: movl $0x8048490,(%esp)
0x080483c1 <+13>: call 0x80482f0 <puts@plt>
0x080483c6 <+18>: leave
0x080483c7 <+19>: ret
Run Code Online (Sandbox Code Playgroud)
我的问题是:
操作系统:ubuntu 10,编译器:gcc
ebp 用作英特尔处理器中的帧指针(假设您使用的是使用帧的调用约定).
它提供了一个已知的参考点,用于定位传入参数(一方面)和局部变量(另一方面),无论您在函数处于活动状态时如何处理堆栈指针.
序列:
push %ebp ; save callers frame pointer
mov %esp,%ebp ; create a new frame pointer
sub $N,%esp ; make space for locals
Run Code Online (Sandbox Code Playgroud)
保存前一个堆栈帧(调用者)的帧指针,加载一个新的帧指针,然后调整堆栈以保存当前"堆栈级别"的内容.
由于参数将已经被推之前设立帧,它们可与被访问[bp+N],其中N是一个合适的偏移量.
同样,因为locals是在帧指针"下"创建的,所以可以使用它们访问它们[bp-N].
该leave指令是单个指令,它撤消该堆栈帧.您曾经不得不手动完成,但英特尔推出了更快的方法来完成它.它在功能上等同于:
mov %ebp, %esp ; restore the old stack pointer
pop %ebp ; and frame pointer
Run Code Online (Sandbox Code Playgroud)
(旧的,手动的方式).
如果我错过了什么,请逐一回答问题:
开始一个新的框架.往上看.
事实并非如此.esp被复制到ebp.这是AT&T表示法(这%reg是一个死的赠品),其中(其中包括)源和目标操作数相对于英特尔表示法交换.
见上面(2)的答案.你从中减去4 esp,而不是相反.
这是一个传递给函数的参数0x80482f0.它没有被加载到esp指向的内存中esp.换句话说,它被推到了堆栈上.由于被调用的函数是puts(见下面的(5)),它将是你想要puts编辑的字符串的地址.
<>地址后面的函数名称.它调用puts函数(可能是标准库中的函数,但不保证).有关PLT的描述,请参见此处.
我已经在leave上面解释了在退出之前展开当前的堆栈帧.在ret简单地从当前函数返回.如果当前的功能是main,它将返回到C启动代码.