当前位置: 首页 > article >正文

Linux函数栈帧

汇编基础

寄存器

rax(accumulator):return value
rbx(base)
rcx(count):4st argument
rdx(data):3st argument
rsi(source index):2st argument
rdi(destination index):1st argument
rbp(base pointer)
rsp(stack pointer)
r8:5st argument
r9:6st argument
r10-r15
rip(instruction pointer)

指令

call指令

相当于执行以下指令:
push %rip
jmp

ret指令

相当于执行以下指令:
pop %rip

leave指令

相当于执行以下指令:
mov %rbp,%rsp
pop %rbp

指令后缀

b(8位)
w(16位)
l(32位)
q(64位)

函数调用

caller执行call之后的栈帧:

arg n
...
arg 2
arg 1
ret       <- rsp

callee开始:
push %rbp
mov %rsp, %rbp
sub $4n, %rsp     # var入栈

arg n     <- rbp + 4(n+1)
...
arg 2     <- rbp + 12
arg 1     <- rbp + 8
ret       <- rbp + 4
rbp       <- rbp
var 1     <- rbp - 4
var 2     <- rbp - 8
...
var n     <- rbp - 4n/rsp

通过x(%rbp)可以访问函数参数(x为正数)和局部变量(x为负数)
执行函数主体,返回值放入rax

callee结束:
mov %rbp, %rsp    # var出栈
pop %rbp          # rbp出栈到rbp
ret               # ret出栈到rip

传参顺序

前6个参数使用rdi、rsi、rdx、rcx、r8、r9,第7个及以后参数使用栈

c代码

int g(int a, int b)
{
    return a + b;
}

int f(int a, int b)
{
    return g(a, b);
}

int main()
{
    return f(1, 2);
}

编译&反汇编

gcc test.c -o test -g
objdump -dS test

c&汇编代码

00000000004004ed <g>:
int g(int a, int b)
{
  4004ed:	55                   	push   %rbp
  4004ee:	48 89 e5             	mov    %rsp,%rbp
  4004f1:	89 7d fc             	mov    %edi,-0x4(%rbp)
  4004f4:	89 75 f8             	mov    %esi,-0x8(%rbp)
    return a + b;
  4004f7:	8b 45 f8             	mov    -0x8(%rbp),%eax
  4004fa:	8b 55 fc             	mov    -0x4(%rbp),%edx
  4004fd:	01 d0                	add    %edx,%eax
}
  4004ff:	5d                   	pop    %rbp
  400500:	c3                   	retq

0000000000400501 <f>:

int f(int a, int b)
{
  400501:	55                   	push   %rbp
  400502:	48 89 e5             	mov    %rsp,%rbp
  400505:	48 83 ec 08          	sub    $0x8,%rsp
  400509:	89 7d fc             	mov    %edi,-0x4(%rbp)
  40050c:	89 75 f8             	mov    %esi,-0x8(%rbp)
    return g(a, b);
  40050f:	8b 55 f8             	mov    -0x8(%rbp),%edx
  400512:	8b 45 fc             	mov    -0x4(%rbp),%eax
  400515:	89 d6                	mov    %edx,%esi
  400517:	89 c7                	mov    %eax,%edi
  400519:	e8 cf ff ff ff       	callq  4004ed <g>
}
  40051e:	c9                   	leaveq
  40051f:	c3                   	retq

0000000000400520 <main>:

int main()
{
  400520:	55                   	push   %rbp
  400521:	48 89 e5             	mov    %rsp,%rbp
    return f(1, 2);
  400524:	be 02 00 00 00       	mov    $0x2,%esi
  400529:	bf 01 00 00 00       	mov    $0x1,%edi
  40052e:	e8 ce ff ff ff       	callq  400501 <f>
}
  400533:	5d                   	pop    %rbp
  400534:	c3                   	retq
  400535:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  40053c:	00 00 00
  40053f:	90                   	nop

栈帧变化过程

不同颜色代表不同函数的栈帧,从上到下依次是__libc_start_main、main、f、g的栈帧
下一级函数的rbp指向上一级函数的rbp
在这里插入图片描述


http://www.kler.cn/a/444554.html

相关文章:

  • aioice里面candidate固定UDP端口测试
  • OpenCV圆形标定板检测算法findGrid原理详解
  • html 中 表格和表单的关系与区别
  • RabbitMQ 路由(Routing)通讯方式详解
  • Restaurants WebAPI(二)——DTO/CQRS
  • 解锁BL后的K40降级
  • 掌握特征提取:机器学习中的 PCA、t-SNE 和 LDA模型
  • [unity3D] 利用 Button 组件实现鼠标悬停显示文字
  • git 不使用第三方软件解决冲突
  • 小米su7 or 保时捷怎么选?使用 Three 实现 3D 汽车展示平台比比看
  • C语言基础十一:指针变量与数组;数组指针及指针数组
  • 【k8s集群应用】K8S二进制安装大致步骤(简略版)
  • windows免登录linux
  • 前端学习-VUE
  • 探秘 Web3:重塑互联网的新力量
  • 【unity小技巧】unity最全的性能优化方案分享以及如何进行性能测试(2024/11/11更新)
  • 【蓝桥杯每日一题】选数异或——线段树
  • 【linux】shell(38)-数组
  • Micro Sip 配置自己的freeswitch服务器地址
  • SpringBoot如何实现缓存预热?
  • 语音识别失败 chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限
  • web全局实现文字的中英文的切换
  • 航电系统组成架构详解!
  • Linux-进程描述符 task_struct 详解(PCB)
  • ZYNQ初识2(zynq_7010)基于vivado,从PL端调用PS端的时钟
  • Cherno C++学习笔记 P42 this关键字