有人可以解释一些简单的汇编代码吗?

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)

我的问题是:

  1. 为什么每次在程序启动时将ebp推入堆栈?运行此程序所需的ebp是什么?
  2. 在第二行为什么ebp被复制到esp?
  3. 我根本无法得到第三条线.我对SUB语法的了解是"sub dest,source",但是在这里如何将esp从4中减去并存储在4中?
  4. 这个值是什么"$ 0x8048490"?为什么它被转移到esp,为什么这个时间是esp在括号中关闭?它是否表示与没有括号的esp不同的东西?
  5. 下一行是对函数的调用,但这是什么"0x80482f0"?
  6. 什么是离开和退出(也许ret意味着返回lib c.)?

操作系统:ubuntu 10,编译器:gcc

pax*_*blo 5

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)

(旧的,手动的方式).

如果我错过了什么,请逐一回答问题:

  1. 开始一个新的框架.往上看.

  2. 事实并非如此.esp被复制到ebp.这是AT&T表示法(这%reg是一个死的赠品),其中(其中包括)源和目标操作数相对于英特尔表示法交换.

  3. 见上面(2)的答案.你从中减去4 esp,而不是相反.

  4. 这是一个传递给函数的参数0x80482f0.它没有被加载到esp指向的内存中esp.换句话说,它被推到了堆栈上.由于被调用的函数是puts(见下面的(5)),它将是你想要puts编辑的字符串的地址.

  5. <>地址后面的函数名称.它调用puts函数(可能是标准库中的函数,但不保证).有关PLT的描述,请参见此处.

  6. 我已经在leave上面解释了在退出之前展开当前的堆栈帧.在ret简单地从当前函数返回.如果当前的功能是main,它将返回到C启动代码.