IA-32函数调用栈帧

IA-32函数调用栈帧

//hello.c
int add(int x,int y){
      return x+y;
}
int main(void){
    int s=11;
    int b=23;
    int c=add(b,s);
    return 0;
}

反汇编代码

m@ubuntu:~$ gcc -S -m32 hello.c -o hello.s -fno-asynchronous-unwind-tables
m@ubuntu:~$ cat hello.s
	.file	"hello.c"
	.text
	.globl	add
	.type	add, @function
add:
	pushl	%ebp
	movl	%esp, %ebp
	call	__x86.get_pc_thunk.ax
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	movl	8(%ebp), %edx
	movl	12(%ebp), %eax
	addl	%edx, %eax
	popl	%ebp
	ret
	.size	add, .-add
	.globl	main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$16, %esp
	call	__x86.get_pc_thunk.ax
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	movl	$11, -12(%ebp)
	movl	$23, -8(%ebp)
	pushl	-12(%ebp)
	pushl	-8(%ebp)
	call	add
	addl	$8, %esp
	movl	%eax, -4(%ebp)
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.section	.text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
	.globl	__x86.get_pc_thunk.ax
	.hidden	__x86.get_pc_thunk.ax
	.type	__x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
	movl	(%esp), %eax
	ret
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits

分析一下汇编代码,main主要压进了这样的数

空
23
11
空
11
23

这个时候看一下objdump出来的数据

gcc -m32 -g hello.s -o hello.out
objdump -d ./hello.out > hello.dmp

得到

000004ed <add>:
 4ed:	55                   	push   %ebp
 4ee:	89 e5                	mov    %esp,%ebp
 4f0:	e8 45 00 00 00       	call   53a <__x86.get_pc_thunk.ax>
 4f5:	05 e7 1a 00 00       	add    $0x1ae7,%eax
 4fa:	8b 55 08             	mov    0x8(%ebp),%edx
 4fd:	8b 45 0c             	mov    0xc(%ebp),%eax
 500:	01 d0                	add    %edx,%eax
 502:	5d                   	pop    %ebp
 503:	c3                   	ret    

00000504 <main>:
 504:	55                   	push   %ebp
 505:	89 e5                	mov    %esp,%ebp
 507:	83 ec 10             	sub    $0x10,%esp
 50a:	e8 2b 00 00 00       	call   53a <__x86.get_pc_thunk.ax>
 50f:	05 cd 1a 00 00       	add    $0x1acd,%eax
 514:	c7 45 f4 0b 00 00 00 	movl   $0xb,-0xc(%ebp)
 51b:	c7 45 f8 17 00 00 00 	movl   $0x17,-0x8(%ebp)
 522:	ff 75 f4             	pushl  -0xc(%ebp)
 525:	ff 75 f8             	pushl  -0x8(%ebp)
 528:	e8 c0 ff ff ff       	call   4ed <add>
 52d:	83 c4 08             	add    $0x8,%esp
 530:	89 45 fc             	mov    %eax,-0x4(%ebp)
 533:	b8 00 00 00 00       	mov    $0x0,%eax
 538:	c9                   	leave  
 539:	c3                   	ret    

call 4ed <add>其中4ed就是add的地址,call的下一条指令地址52d会被push到栈

这时候栈帧变成

0xc(%ebp) 11
0x8(%ebp) 23
0x4(%ebp) 52d
0x0(%ebp) 旧的ebp
---%ebp

于是add的mov 0x8(%ebp),%edxmov 0xc(%ebp),%eax分别将edx赋值为23,将eax赋值为11。add %edx,%eax指令和刚才寄存器edx和寄存器eax的参数值副本执行加法运算,计算后的结果将保存到eax寄存器。因为eax是作为返回值参数传递的。

这里发现add的栈帧是0大小,所以pop %ebp就直接将原来main的旧ebp保存到ebp寄存器里,相当于切换回main的栈帧。此时,esp也会自动变大,因为弹出东西了,指向为main栈帧的顶部。

ret就是把返回地址52d弹回到eip中。从而继续main的下一条指令。

这个时候,main中add 0x8,%esp相当于收回了用于传参的两个内存空间,mov %eax,-0x4(%ebp)相当于将add的结果保存在栈底那个位置,最后内存布局如下

---ebp
34
23
11
---esp

end

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值