【问题标题】:Labels as Values in Inline Assembly Macros标签作为内联汇编宏中的值
【发布时间】:2015-08-15 04:35:40
【问题描述】:

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

我天真地尝试过以这种方式这样做:

#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 中。

【问题讨论】:

    标签: c assembly x86 arm inline-assembly


    【解决方案1】:

    实际上有一个完整的指令用于将标签的地址放入寄存器:ADR

    由于它在 PC 上通过算术工作,它完全独立于位置并且没有无限范围,但这里似乎都不是问题 - 利用汇编程序的“当前指令”伪标签 .,示例问题变成:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • ldr r0, =label 也可以,除非文字池太远。移动指令没有足够的位将 32 位值加载到寄存器中。我还注意到用任何其他字符串替换 1b 也可以编译,所以我认为我的语法有点不对劲。我怀疑内联程序集找不到标签 1b 并且默认为 0。
      • @squirem:你错过了我的第二段吗?尝试链接,而不仅仅是组装。感谢您提供有关 ARM asm 的线索。我已经习惯了 x86,我什至没有考虑在固定 insn 长度的 ISA 中使用 32 位立即数的困难。
      • @squirem 如果汇编器找不到标签,它会大声抱怨并失败。正如 Peter 暗示的那样,assembler 不知道绝对地址是什么,所以它编码 0 并在对象中发出一个重定位,以便链接器稍后修复 - 请注意汇编器必须如何生成一个真正的标签 (.L11) 代替其本地标签。试试objdump -r 看看缺失的部分;)
      猜你喜欢
      • 2011-04-23
      • 2012-04-22
      • 1970-01-01
      • 2019-10-03
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      相关资源
      最近更新 更多