一 概述
二 类型
三 语句
四 函数
五 数据
六 内存
七 代码
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
3.1 调用约定
调用约定(Calling Conventions)是 应用二进制接口 (ABI)的组成部分,内容包括:
- 参数和返回值如何传递?(寄存器还是调用栈)
- 按什么顺序?
- 谁负责内存分配和清理?
早期常见的有 stdcall, cdecl, fastcall 等,x64 主流只有 Microsoft x64、System V AMD64 两种。
$ readelf -h ./test ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian OS/ABI: UNIX - System V
System V AMD64
主要用在 Solaris、FreeBSD、Linux、macOS 等系统。
- 前
6
参数(整数、指针、结构 ...)依次使用RDI
、RSI
、RDX
、RCX
、R8
、R9
。
- 如某参数超过 8 字节,用连续的两个寄存器。
- 如某参数超过 16 字节,则入栈。对应寄存器给后续参数使用。
- 浮点数前
8
参数,使用XMM0 ~ XMM7
。
- 整形和浮点混用时,交叉使用 RDI... 和 XMM 等 14 个寄存器。
- 剩余参数(含前 6 超过 16 字节等参数)
从右往左
依次入栈。
- 返回值小于等于 8 字节,使用
RAX
。 - 小于等于 16 字节,剩余部分用
RDX
。 - 大于 16 字节,由调用方负责返回值内存,以寄存器传递内存地址。
typedef struct { long long x; int y; long long z; } data_t; void test (data_t d, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) { ... } --- d > 16 bytes --- RDI: a1 RSI: a2 RDX: a3 RCX: a4 R8 : a5 R9 : a6 PUSH a9 PUSH a8 PUSH a7 PUSH d.z, d.y, d.x // len(d) > 16
void test (int a, float b, int c, float d) --- 交叉使用 --- RDI : a XMM0: b RSI : c XMM1: d
typedef struct { long long x; int y; } data_t; data_t test () { ... } ---- 8 < ret <= 16 bytes --- RAX: ret.x RDX: ret.y
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论