【问题标题】:aarch64 g++: MOV in __asm only moves lower 32 bits of a 64-bit value [closed]aarch64 g++:__asm 中的 MOV 仅移动 64 位值的低 32 位 [关闭]
【发布时间】:2020-05-08 09:43:47
【问题描述】:

我正在使用 arch64-linux-gnu-g++(版本 7.5.0)和标准设置为 C++17 为 aarch64 机器交叉编译我的代码。我的代码包括以下内容:

  uint64_t inRef = 0x ... ;  

  ...  

  __asm("MOV X8, %[input_i];"  
      :  
      : [input_i] "r" (inRef)  
      : "x8"  
  );

我正在将值打包到 inRef 中,并试图让寄存器 X8 保存 inRef 的值,以便稍后在程序中处理。当我打印出 inRef 的值时,我可以确认它确实包含 64 位值。

但是,我在程序执行中看到的是只有 inRef 的底部 32 位实际上被传递给 X8,即使 inRef 是一个 uint64_t 并且作为 aarch64 系统的一部分的 X8 也是 64 位。我已经尝试查看约束字符(“r”),但根据文档,这应该是指 64 位寄存器 [1]。我还尝试使我的代码更明确,如 [2] 中所示,如下所示:

  register std::uint64_t x7 asm("x7") = 0x ... ;  

  ...  

  __asm__ volatile("MOV X8, %[input_i];"  
      :   
      : [input_i] "r" (x7)  
      : "x8"  
  );   

不幸的是,发生了同样的错误。我已经验证我的机器实际上是 aarch64 机器,它的 X 寄存器确实是 64 位的,所以我怀疑问题可能出在代码或编译中。综上所述,如何将 aarch64 中的 64 位变量全部移动到寄存器中?

参考:
[1]http://infocenter.arm.com/help/topic/com.arm.doc.100067_0610_00_en/qjl1517569411293.html
[2]Android Studio 64 bit inline ARM assembly

【问题讨论】:

标签: c++ c++17 cross-compiling arm64


【解决方案1】:

您所做的实际上看起来是正确的。

对于简单的 asm 包括,您可以使用“索引”引用变量,如 %0%1 等。数字是 clobber 列表中变量的索引

void f0 (void* self, uint64_t ref) 
{
    asm volatile("mov x8, %0" :: "r" (ref) : "x8");
}

在某些情况下,您可能希望使用属性 %x0 对 64 位寄存器或 %w0 对 32 位寄存器强制执行 64 位寄存器。当 32bit 值被强制进入 64b 寄存器时,这是很有用的。

void f1 (void* self, uint64_t ref)
{
    asm volatile("mov x8, %x0" :: "r" (ref) : "x8");
    // asm volatile("mov w9, %0" :: "r" (ref) : "x9"); <-- 'mov w9, x1' is generated, that's unsupported op
    asm volatile("mov w9, %w0" :: "r" (ref) : "x9"); <-- this is fine
}

或者在你尝试的时候在clobber中使用名称。 x/w 属性仍然可以使用

void f2 (void) 
{
    uint64_t ref{0xdeadbeefdeadbeef};  
    asm volatile("mov x8, %x[val]" ::[val] "r" (ref) : "x8");
}

Godbolt 上也一样:https://godbolt.org/z/z6vKqx6bT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2010-09-15
    相关资源
    最近更新 更多