内联汇编
介绍
Wave的内联汇编是通过 asm { ... 通过 }` 块编写。
在Wave代码中可以直接控制寄存器、内存、系统调用路径。
当前支持的目标:
- Linux
x86_64 - Linux
aarch64 - macOS (Darwin)
arm64 - freestanding
x86_64 - freestanding
aarch64 - freestanding
riscv64
Windows와 32비트 타깃은 아직 지원하지 않습니다.
基本形式
asm可以用于语句,也可以用于表达式。
asm {
"指令"
in("constraint_or_reg") value
out("constraint_or_reg") target
clobber("item")
}
组成要素:
- 字符串行: 实际汇编指令
in(...): 输入操作数out(...): 输出操作数clobber(...): 被破坏的寄存器/状态/内存提示
asm 语句
在不需要返回值的情况下作为一般语句使用。
var ret: i64 = 0;
asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret
}
out(...) 可以放置多个。
asm 表达式
可以用作直接生成值的表达式。
var result: i64 = asm {
"mov rax, 123"
out("rax") result
};
注意:
asm表达式只允许一个out(...)。
in(...) / out(...) 约束
in("..."), out("...")的字符串是以下两者之一。
- 具体寄存器
- 예:
"rax","rdi","x0","w1","a0","t0","x10"
- 约束类(constraint class)
- 例如:
"r","m","rm"
例:
in("r") &buf
out("rax") ret
输出目标(`out(...) 根据当前实现,推荐使用以下模式。
- 变量:
out("rax") ret - 指针反向引用:
out("rax") deref p
clobber(...)
clobber(...) 可以一次接收多个项目,也可以多次使用。
asm {
"xor rax, rax"
clobber("rax")
clobber("rcx", "rdx")
clobber("memory")
}
主要项目:
- 寄存器:
"rax","x0"等 - 特殊:
"memory","cc"(基于目标的内部规范化)
编译器在保守安全模式下会自动添加基本的clobber。
(memory, flags/cc 계열 등; RISC-V freestanding에서는 주로 memory)
操作数占位符 ($0, $1, ...)
在命令字符串中引用操作数时使用 $N。
asm {
"mov QWORD PTR [$0], 777"
in("r") &buf
clobber("memory")
}
注意:
- 即使使用
%0样式,也会在内部转换为$0样式。
输入操作数当前支持范围
in(...) 值目前支持以下形式:
- 变量标识符
- 整数字面量
- 字符串字面量
&identifierderef identifier- 负整数/实数字面量
复杂的通用表达式可能会受到限制,因此建议在需要时先放入临时变量中传递。
注意事项
内联汇编部分绕过了类型系统的保护。 错误的寄存器指定、约束冲突、漏掉 clobber 可能导致错误的代码生成或运行时行为。
建议:
- 首先确定目标 ABI 和调用约定
- 明确管理输入/输出寄存器和 clobber
- 如果直接操作内存,请同时声明
clobber("memory")。