官方文档内联汇编规则
翻译自https://ziglang.org/documentation/master/#toc-Assembly
pub fn syscall1(number: usize, arg1: usize) usize {
// 内联汇编是一个有返回值的表达式。
// 这个表达式以`asm`开始
return asm
// volatile是一个可选的修饰符,告诉Zig该内联汇编表达式有副作用
// 无volatile的情况下,如果返回值未被使用,Zig将可能会删除该内联汇编
volatile (
// 下一项是用来表示汇编的编译期字符串
// 在这个字符串里,在这个字符串中,可以使用 %[ret]、%[number] 或 %[arg1] 来代表寄存器,
// 以指定在使用寄存器约束字符串时 Zig 用于参数或返回值的寄存器。
// 不过本示例代码并没有这个用法
// %字符串可以通过双倍的百分号%%来获得。
// 通常在这部分会使用多行字符串语法。
\\syscall
// 下一项是输出部分。在未来,Zig 可能会支持多个输出,这取决于
// https://github.com/ziglang/zig/issues/215 如何解决。
// 同时也允许无输出。在这种情况下,这个冒号后面直接接着输入部分的冒号。
:
// 这指定了上面汇编字符串中使用的 %[ret] 语法中的名称。
// 本示例中没有使用它,但语法是强制性的。(不太理解是哪方面的强制性)
[ret]
// 下一项是输出约束字符串。在 Zig 中,这个特性是不稳定的,
// 因此必须使用 LLVM/GCC 文档来理解语义。
// 详见 https://llvm.org/docs/LangRef.html#inline-asm-constraint-string
// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
// 本示例中,约束字符串表示:内联汇编指令的结果值是 $rax 中的任意值。
"={rax}"
// 下一项是一个值绑定,或者 -> 后跟一个类型。
// 类型是内联汇编表达式的结果类型。如果是一个值绑定,
// 那么可以在汇编字符串使用 %[ret] 语法来引用与该值绑定的寄存器。
(-> usize),
// 下一项是输入列表。这些输入的约束意味着,
// “当执行汇编代码时,$rax 必须具有 number 的值,$rdi 必须具有 arg1 的值”。
// 允许任意数量的输入参数。
: [number] "{rax}" (number),
[arg1] "{rdi}" (arg1),
// 下一项是破坏列表。这部分声明一组寄存器,其值在执行此汇编代码时不会被保留。
// 这不包括输出或输入寄存器。
// 特殊的破坏值 "memory" 意味着汇编写入未声明的任意内存位置,不仅限于已声明的间接输出所指向的内存。
// 本示例中,我们列出了 $rcx 和 $r11,因为已知内核系统调用不保留这些寄存器的值。
: "rcx", "r11"
);
}
传递参数
X86_64传递参数的顺序
整数寄存器:RDI、RSI、RDX、RCX、R8、R9、栈。
浮点寄存器:XMM0、XMM1、XMM2、XMM3、XMM4、XMM5。
当参数数量超过六个时,额外的参数会被推送到栈上,从右往左依次排列。这意味着第七个参数会出现在较高的地址上,以此类推。
参数从右到左在栈上入栈,但在调用函数之前,栈会被对齐到16字节的边界。这意味着如果参数总数是奇数,会填充一个额外的8字节以保持栈的对齐。
Windows下参数传递
整数寄存器:RCX、RDX、R8、R9、栈。
浮点寄存器:XMM0、XMM1、XMM2、XMM3。
当参数数量超过四个时,额外的参数会被推送到栈上,从右往左依次排列。这意味着第五个参数会出现在较高的地址上,以此类推。
参数从左到右在栈上入栈,但在调用函数之前,栈会被对齐到16字节的边界。这意味着如果参数总数是奇数,会填充一个额外的8字节以保持栈的对齐。
Arm与Arm64
Linux下
Arm32
整数寄存器: r0、r1、r2 、 r3 、栈。
浮点寄存器: s0、s1、s2 、 s3 、栈。
Arm64
整数寄存器: x0 到 x7 、栈。
浮点寄存器: d0 到 d7 、栈。
Windows下
整数寄存器: x0、x1、x2、x3、栈。
整数寄存器:d0 到 d7、栈。
内联asm约束字符串
LLVM Language Reference Manual — LLVM 18.0.0git documentation --- LLVM 语言参考手册 — LLVM 18.0.0git 文档
objdump查看汇编
# 指定Intel汇编(默认AT&T汇编)
llvm-objdump -S -M intel xxx.exe