我正在 Mac/aarch64 上运行书中的 代码示例,并收到编译错误。
fn dereference(ptr: *const usize) -> usize {
let mut res: usize;
unsafe {
asm!("mov {0}, [{1}]", out(reg) res, in(reg) ptr)
};
res
}
我得到:
error: expected compatible register or logical immediate
--> src/main.rs:20:15
|
20 | asm!("mov {0}, [{1}]", out(reg) res, in(reg) ptr)
| ^
|
note: instantiated into assembly here
--> <inline asm>:1:10
|
1 | mov x8, [x0]
| ^
搜索了错误消息后,我相信架构与它有关,但我还没有弄清楚如何修复它。我正在查看 Rust inline assembly 文档,但由于该主题对我来说是全新的,因此我无法将无法编译的示例映射到我在文档中看到的内容。
mov x8, [x0]
看起来像带有 AArch64 寄存器名称的 x86-64 语法。 (从您的回答来看,您似乎刚刚找到了一个示例,可能没有提及它是针对 x86-64 的,并尝试将其编译为 AArch64。)
AArch64 是一种加载/存储架构:特殊指令(如
ldr
和 str
)是唯一访问内存的指令,例如ldr x8, [x0]
。查看解引用指针的 Rust 函数的编译器输出,例如Godbolt 显示了将 aarch64-apple-darwin 的纯 Rust 取消引用编译为 ldr x0, [x0]
和 ret
。
相比之下,x86-64 使用
mov
进行加载、存储和寄存器复制:大多数读取和写入寄存器的 x86-64 指令也可用于内存源或目标。 (这是CISC与RISC在两种架构设计上的差异之一。)
阅读有关 AArch64 asm 的教程,例如https://modexp.wordpress.com/2018/10/30/arm64-assemble看起来很合理;当我搜索
inline assembly x86-64 aarch64 ldr
时,谷歌找到了它。它有一个简短的部分比较了 x86 与 AArch64 汇编,但这只是 reg、reg 指令的一些等效项的表格。 movzx eax, byte [rdi]
的 AArch64 等效项是 ldrb w0, [x0]
,而 movzx eax, dil
是 uxtb w0, w0
,同样具有零扩展或符号扩展窄负载的特殊说明。
实际上它们是完全不同的架构。很多事情的完成方式是完全不同的,例如指令默认不设置FLAGS,助记词上需要加S后缀。 (除了
cmp
和 tst
,它们仅用于写入标志。)并且不是推送/弹出,而是带有后增量寻址的 stp
/ ldp
。 (始终以一对 64 位寄存器的形式完成,以保持堆栈按 16 对齐。)
当然,花了很多时间但直到我发布这个问题后,我才找到答案。
Arm64
装配中的模板应该是"mov {0}, {1}"
,而不是"mov {0}, [{1}]"
。
有什么帮助:
add
示例也无法为我编译。
add
上谷歌搜索
Arm64
后,我发现了汇编备忘单,它表明
add
的语法在此架构上与
x86/x86-64
完全不同(3 个参数而不是 2 个)。
mov
指令的语法,发现了问题。