Veg*_*ife 5 assembly x86-64 abi cpu-registers calling-convention
我经常忘记系统调用中每个参数需要使用的寄存器,每次我忘记时我都会访问这个问题。
x86_64 用户空间函数调用的整数/指针参数的正确顺序是:
%rdi、%rsi、%rdx、%rcx和%r8。%r9(可变参数函数采用 AL = FP 参数的数量,最多 8)
或者对于系统调用,%rax(系统调用调用号)和相同的参数,除了%r10代替%rcx.
记住这些寄存器而不是每次都用谷歌搜索这个问题的最佳方法是什么?
Pet*_*des 10
如果您还记得 Cmemcpy的 arg 顺序以及工作原理,那么这就是记住 x86-64 System V 的大部分方法。rep movsb
该设计的memcpy(dst, src, size)实现成本较低rep movsb,除了在更多函数中未使用 RCX 之外,因为变量计数移位所需的频率比 RDX 所需的频率更高。
那么R8和R9是前两个“高”寄存器。使用它们需要一个 REX 前缀,这会在指令中花费一个额外字节的代码大小,否则不需要。因此,对于最后 2 个参数来说,它们是一个明智的选择。(Windows x64 同样选择使用 R8、R9 作为最后 2 个寄存器参数)。
实际的设计过程涉及最小化指令数和代码大小的成本权衡,以便使用当时的 GCC AMD64 端口编译某些内容(可能是 SPECcpu)。我不知道内联memcpy as是否rep movsb相关,或者 glibc 当时是否真的以这种方式实现它,或者什么。
我对Why does Windows64 use a different Calling convention from all other OSes on x86-64? 的回答 引用了调用约定设计决策的一些来源。(早期 x86-64.org 邮件列表中来自 GCC 开发人员的帖子,特别是 Jan Hubicka,他在提出这个命令之前尝试了一些寄存器命令。)
请特别注意记住订单中的 RDX、RCX 部分是以下引用:
我们试图在序列的早期避免 RCX,因为它是通常用于特殊目的的寄存器,如 EAX,因此在序列中丢失它具有相同的目的。而且它不能用于系统调用,我们希望使系统调用序列尽可能匹配函数调用序列。
R10在系统调用约定中取代了RCX,因为指令syscall本身会破坏RCX(用它来保存RIP,避免使用用户空间堆栈,并且它不能使用内核堆栈,因为它将堆栈切换留给软件)。就像它如何使用 R11 来保存 RFLAGS 一样。
保持尽可能相似可以让 libc 包装器仅仅mov %rcx, %r10而不是通过多个参数进行混洗来填补空白。R10 是继 R8 和 R9 之后的下一个可用寄存器。
Diane 的silk dress cost $89(由CS:APP博客推荐)
| 归档时间: |
|
| 查看次数: |
646 次 |
| 最近记录: |