X86和X86-64的函数栈帧结构以及调用约定

本文探讨了X64与X86平台上的函数栈帧结构差异,特别是X64如何通过增加寄存器使用来改变函数参数传递方式。作者详细对比了两种架构下的栈帧布局,并提供了丰富的参考资料。

写在前头

对于函数栈帧(stack frame)的概念我是早就知道的,对x86的栈帧结构也算的上熟悉,之所以写这篇文章是因为我发现X64平台函数参数传递与X86有很大不同,X64增加了很多寄存器的使用。索性总结一下,供自己以后查阅学习!如有错误的地方,还请读者指出!

写这篇文章主要参考了Eli Bendersky的两篇文章,个人非常喜欢他的文章,总能用探索式的博文将技术细节呈现在我的眼前!

x86函数栈帧结构

 

x64函数栈帧结构

 

参考链接:

Where the top of the stack is on x86

Stack frame layout on x86-64》(中文翻译

System V ABI

X86-64寄存器和栈帧

栈帧 Stack Frame

Intel x86 Function-call Conventions - Assembly View

Journey to the Stack

Calling Conventions

深入浅出GNU X86-64 汇编》

X86-64寄存器和栈帧

x86-64 下函数调用及栈帧原理

How does one backtrace up the stack when frame pointers are omitted?

x86 - 64 函数调用约定涉及寄存器使用参数传递等多个方面。 ### 寄存器使用 x86 - 64 指令架构要求至少有 16 个 64 位的通用寄存器,每个寄存器有不同的用途: - `%rax`:存储过程调用返回值(return value)。 - `%rbx`:在某些情况下可用于存储数据。 - `%rcx`:存储过程调用的第四个参数。 - `%rdx`:存储过程调用的第三个参数。 - `%rbp`:存储当前帧的基地址。 - `%rsp`:存储顶地址。 - `%rsi`:存储过程调用的第二个参数。 - `%rdi`:存储过程调用的第一个参数。 - `%r8`:存储过程调用的第五个参数。 - `%r9`:存储过程调用的第六个参数。 - `%r10 - %r11`:可用于临时存储数据。 - `%r12 - %r15`:通常用于保存数据等操作 [^2]。 ### 与 x86 寄存器对比 x86 只有 8 个通用寄存器(`eax`, `ebx`, `ecx`, `edx`, `ebp`, `esp`, `esi`, `edi`)。x64 将它们扩展到 64 位(前缀由 “e” 变为 “r”),并新增了 8 个(`r8`, `r9`, `r10`, `r11`, `r12`, `r13`, `r14`, `r15`)。由于 x86 的部分寄存器有特殊隐含意义,并非真正作为通用寄存器使用(如 `ebp` `esp`),所以有效增加的寄存器数量比表面上看起来更多 [^3]。 ### 的使用 在函数调用中,也起着重要作用,用于存储局部变量、保存寄存器状态等。 ### 代码示例 以下是一个简单的汇编代码示例,展示函数调用中寄存器的使用: ```asm # 函数入口 .global _start _start: # 设置函数参数 mov $1, %rdi # 第一个参数 mov $2, %rsi # 第二个参数 mov $3, %rdx # 第三个参数 mov $4, %rcx # 第四个参数 # 调用函数 call my_function # 退出程序 mov $60, %rax xor %rdi, %rdi syscall my_function: # 函数体 # 这里可以使用传入的参数进行计算 add %rdi, %rsi # 示例操作 mov %rsi, %rax # 设置返回值 ret ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值