在 aarch64 上使用 asm!("mov...") 编译错误

问题描述 投票:0回答:2

我正在 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 文档,但由于该主题对我来说是全新的,因此我无法将无法编译的示例映射到我在文档中看到的内容。

rust inline-assembly arm64
2个回答
0
投票

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 对齐。)


-1
投票

当然,花了很多时间但直到我发布这个问题后,我才找到答案。

Arm64
装配中的模板应该是
"mov {0}, {1}"
,而不是
"mov {0}, [{1}]"

有什么帮助:

  1. 我决定从头开始,阅读 Rust By Examples 关于内联汇编的章节。我发现最简单的 add
     示例也无法为我编译。
  2. add
     上谷歌搜索 
    Arm64
     后,我发现了
    汇编备忘单,它表明 add
     的语法在此架构上与 
    x86/x86-64
     完全不同(3 个参数而不是 2 个)。
  3. 我更仔细地观察了
  4. mov
     指令的语法,发现了问题。
© www.soinside.com 2019 - 2024. All rights reserved.