在内联汇编宏中作为值的标签

Labels as Values in Inline Assembly Macros

我想知道如何在内联汇编中加载具有标签值的寄存器。

我天真地尝试过以这种方式进行操作:

#define inline_macro(a) \
    asm volatile("1: movw %[rega], #:lower16:1b\n" \
                 "   movt %[rega], #:upper16:1b\n" \
                 : [rega] "+r" (a)       \
                 :                       \
                 :                       \
    );

int main(void){
    register int   i     asm("r2");
    register void* value asm("r1");
    i++;
    i += 2;
    inline_macro(value);
    return i;
}

但是,对象转储显示正在生成此汇编代码:

00000000 <main>:
   0:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!)
   4:   e28db000    add fp, sp, #0
   8:   e1a03002    mov r3, r2
   c:   e2833001    add r3, r3, #1
  10:   e1a02003    mov r2, r3
  14:   e1a03002    mov r3, r2
  18:   e2833002    add r3, r3, #2
  1c:   e1a02003    mov r2, r3

00000020 <.L11>:
  20:   e3001000    movw    r1, #0
  24:   e3401000    movt    r1, #0
  28:   e1a03002    mov r3, r2
  2c:   e1a00003    mov r0, r3
  30:   e24bd000    sub sp, fp, #0
  34:   e49db004    pop {fp}        ; (ldr fp, [sp], #4)
  38:   e12fff1e    bx  lr

我想要的是将值 0x20 加载到寄存器 r1。

我不知道 arm asm,但你正在尝试获取 movw 指令的地址? ARM 真的需要两个单独的 16 位 mov 指令吗?

看起来您正在反汇编 .o,其中链接器没有用它们的实际值替换符号引用,并且您看到 0 作为占位符。

因为我认为你的代码不依赖于寄存器的旧值,你应该将它用作只写输出操作数(=r),而不是读写操作数(+r).

实际上有一整条指令可以将标签的地址存入寄存器:ADR

由于它在 PC 上通过算术工作,因此它完全与位置无关并且没有无限范围,但这似乎都不是问题 - 利用汇编程序的 "current instruction" 伪标签 .,问题中的例子变成:

#define inline_macro(a) \
    asm volatile("adr %[rega], . \n"     \
                 : [rega] "=r" (a)       \
                 :                       \
                 :                       \
    );