AT&T 指令简记

* LEA指令

    lea 7(%edx, %edx,4), %eax    ==> 将寄存器%eax的值置为 5 * %edx + 7.

    base(offset, index, i) 计算方法为base + offset + index * i


* leave指令

    等价于:

    movl %ebp %esp

    popl %ebp

(gdb) disassemble 
Dump of assembler code for function foo:
   0x08048394 <+0>:	push   %ebp
   0x08048395 <+1>:	mov    %esp,%ebp
   0x08048397 <+3>:	sub    $0x10,%esp
   0x0804839a <+6>:	movl   $0x0,-0x4(%ebp)
   0x080483a1 <+13>:	mov    0xc(%ebp),%eax
   0x080483a4 <+16>:	mov    0x8(%ebp),%edx
   0x080483a7 <+19>:	lea    (%edx,%eax,1),%eax
=> 0x080483aa <+22>:	leave  
   0x080483ab <+23>:	ret    
End of assembler dump.
(gdb) i r
eax            0x2	2
ecx            0xfd561843	-44689341
edx            0x0	0
ebx            0x28bff4	2670580
esp            0xbffff1c8	0xbffff1c8  #leave前esp的值为0xbffff1c8
ebp            0xbffff1d8	0xbffff1d8  #leave前ebp的值为0xbffff1d8,该值在执行leave时相当于执行一次pop,即0xbffff1d8+4=0xbffff1dc将作为esp的新值
esi            0x0	0
edi            0x0	0
eip            0x80483aa	0x80483aa <foo+22>
eflags         0x200282	[ SF IF ID ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb) p/d ($ebp-$esp)/4
$3 = 4
(gdb) x/5xw $esp
0xbffff1c8:	0xbffff1f8	0x080483f9	0x0015ecbd	0x00000000
0xbffff1d8:	0xbffff1f8  #$ebp指向的栈底的值为0xbffff1f8,也就是前一栈帧的帧底,leave执行后该值将是ebp的新值
(gdb) ni #执行leave指令
0x080483ab in foo (a=0, b=2) at test.c:4
4	}
(gdb) i r
eax            0x2	2
ecx            0xfd561843	-44689341
edx            0x0	0
ebx            0x28bff4	2670580
esp            0xbffff1dc	0xbffff1dc   #leave后ebp的值为0xbffff1dc
ebp            0xbffff1f8	0xbffff1f8   #leave后ebp的值为0xbffff1f8
esi            0x0	0
edi            0x0	0
eip            0x80483ab	0x80483ab <foo+23>
eflags         0x200282	[ SF IF ID ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb) x/1xw $esp 
0xbffff1dc:	0x080483d6 #这个状态正好相对就于call后的状态,即esp指向的正是lr返回地址,执行ret后0x080483d6将被弹入eip继续执行程序
(gdb) disassemble 
Dump of assembler code for function foo:
   0x08048394 <+0>:	push   %ebp
   0x08048395 <+1>:	mov    %esp,%ebp
   0x08048397 <+3>:	sub    $0x10,%esp
   0x0804839a <+6>:	movl   $0x0,-0x4(%ebp)
   0x080483a1 <+13>:	mov    0xc(%ebp),%eax
   0x080483a4 <+16>:	mov    0x8(%ebp),%edx
   0x080483a7 <+19>:	lea    (%edx,%eax,1),%eax
   0x080483aa <+22>:	leave  
=> 0x080483ab <+23>:	ret    
End of assembler dump.
(gdb) ni
main () at test.c:12
12	    return 0;
(gdb) disassemble 
Dump of assembler code for function main:
   0x080483b1 <+0>:	push   %ebp
   0x080483b2 <+1>:	mov    %esp,%ebp
   0x080483b4 <+3>:	sub    $0x18,%esp
   0x080483b7 <+6>:	movl   $0x0,-0x4(%ebp)
   0x080483be <+13>:	call   0x80483ac <fn>
   0x080483c3 <+18>:	movl   $0x2,0x4(%esp)
   0x080483cb <+26>:	mov    -0x4(%ebp),%eax
   0x080483ce <+29>:	mov    %eax,(%esp)
   0x080483d1 <+32>:	call   0x8048394 <foo>
=> 0x080483d6 <+37>:	mov    $0x0,%eax
   0x080483db <+42>:	leave  
   0x080483dc <+43>:	ret    
End of assembler dump.
(gdb) 

    综上,leave正是函数入口的

    push   %ebp
    mov    %esp,%ebp

   的反操作.

   而ret则是call的反操作. 正反操作成对后,从栈(尺寸度量)的角度考虑,变化为零.

   这正是函数调用中,栈完美运行的奥秘.

还有一种情况比较特殊,就是这样的代码
void fn(){}

080483ac <fn>:
 80483ac:       55                      push   %ebp
 80483ad:       89 e5                   mov    %esp,%ebp
 80483af:       5d                      pop    %ebp
 80483b0:       c3                      ret

从汇编上看,函数逻辑代码部分本身没有用到栈
 push   %ebp
与
pop    %ebp
构成了一对正反操作.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值