【问题标题】:Memory offsets in inline assembly内联汇编中的内存偏移
【发布时间】:2015-07-01 19:32:40
【问题描述】:

在 A64 汇编器中,有不同的方式来指定地址。

/*
[base{,#0}]                 Simple register (exclusive) - Immediate Offset
[base{,#imm}]               Offset - Immediate Offset
[base,Xm{,LSL #imm}]        Offset - Register Offset
[base,Wm,(S|U)XTW {#imm}]   Offset - Extended Register Offset
[base,#imm]!                Pre-indexed - Immediate Offset
[base],#imm                 Post-indexed - Immediate Offset
label                       PC-relative (literal) load - Immediate Offset
*/

我想在内联汇编器中使用“Offset - Immediate Offset”。

__asm__("ldp x8, x9, %0, 16 \n\t"
        :
        : "m" (*somePointer)
        : "x8", "x9");

这被翻译成

ldp x8, x9, [x0], 16

我的目标是达到

ldp x8, x9, [x0, 16]

如何使用内联汇编编写这样的指令?

【问题讨论】:

  • 我不知道你怎么能用只有 1 个参数的 %1 ?使用寄存器约束怎么样?警告:我还没有尝试过,但是asm("ldp x8, x9, [%0, %1]" : : "r" (somePointer), "i"(16) : "x8", "x9"); 之类的呢?
  • 修复了这个问题 - 它显然应该是 %0。从具有更多输入/输出的较长语句中提取,并忘记更新参数:-) 这些提示对编译器来说不是很重要,以便它知道我的代码访问了哪些内存区域吗?例如如果我在写上下文中使用它,编译器可能需要知道我破坏了哪些内存区域 - 在这种情况下,寄存器约束将不起作用?
  • 确实如此。所以由于编译器实际上并没有解析 asm,你可以这样做:asm("ldp x8, x9, [%0, %1]" : : "r" (somePointer), "i"(16), "m" (*somePointer) : "x8", "x9");(即有约束,但不要引用它)。或添加“记忆”破坏者。请注意,正如所写,您只是告诉编译器 asm 读取内存,而不是更改它。

标签: c memory assembly inline-assembly arm64


【解决方案1】:

我没有 ARM 64 位工具链来测试这个,但你应该可以做这样的事情:

asm("ldp x8, x9, %0\n\t"
    :
    : "Ump" (*((__int128 *) somePointer + 1))
    : "x8", "x9");

Ump 约束将内存操作数限制在整数 LDP 指令允许的范围内,否则它的工作方式与 m 约束类似。如果somePointer 已经是一个指向 128 位类型的指针,您可以使用 somePointer[1] 作为操作数。

如果上述方法不起作用,那么 David Wohlferd 的建议应该是:

asm("ldp x8, x9, [%0, %1]" 
    : 
    : "r" (somePointer), "i"(16), "m" (*somePointer) 
    : "x8", "x9"); 

【讨论】:

    猜你喜欢
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 2012-10-20
    • 1970-01-01
    • 2012-11-05
    • 2018-07-09
    相关资源
    最近更新 更多