使用内联汇编读取变量

Reading variable with inline assembly

我想知道,根据实际指令读取输入变量是否有限制?

我正在尝试读取内联汇编中的输入变量,以便 .rept 指令重复一条指令 x 次。

但是,汇编程序抱怨: Error: negative count for REPT - ignored

这是我的方法:

const int x = 42;
__asm__ volatile (".rept %[in]" :: [in] "m" (x));
__asm__ volatile (".endr");

尝试将变量值加载到寄存器中时如预期的那样工作:

int function(void) {
    const int x = 42;
    __asm__ volatile ("mov %[in], %%eax" :: [in] "m" (x));
    __asm__ volatile ("ret");
}

returns 42,反汇编符合预期。

我试着在汇编中写这个,看看常量是否可以与 .rept 指令一起使用,它确实如此

global _start

section .data
    nvalue  equ     39

section .text

_start:
    push    rbp
    mov     rbp,    rsp

    %rep nvalue
        nop
    %endrep

    mov     rax,    60
    mov     rdi,    nvalue
    syscall

反汇编符合预期:

Disassembly of section .text:

0000000000401000 <_start>:
  401000:       55                      push   rbp
  401001:       48 89 e5                mov    rbp,rsp
  401004:       90                      nop
  ...
  40102d:       90                      nop
  40102e:       b8 3c 00 00 00          mov    eax,0x3c
  401033:       bf 2a 00 00 00          mov    edi,0x2a
  401038:       0f 05                   syscall

我是不是把 .rept%rep 弄混了,它们不代表相同的操作吗?

任何帮助将不胜感激。

如评论中所述,i 操作数通常会插入前导 $ 符号,这在 AT&T 语法中作为立即操作数是正确的,但不适合像 .rept。您可以使用 c 修饰符来抑制它,请参阅 Section 6.47.2.8 of the GCC manual:

void many_nops(void) {
    const int num = 42;
    asm(".rept %c0 ; nop ; .endr" : : "i" (num));
}

这将内联 42 nop 条指令。当然,这只有在 num 可以折叠为编译时常量的情况下才有效;特别是你必须优化编译才能工作。

Try on godbolt

您还可以将 Intel asm 语法与 -masm=intel 结合使用,其中常量首先不会获得前导 $

请注意,您的内联 asm 存在许多其他问题(您不能从内联 asm ret,不应该在多个 asm 语句之间拆分代码,等等)所以您可能想先阅读 https://whosebug.com/tags/inline-assembly/info.

上的一些常见问题解答

.rept%rep 的问题:第一个是 GNU 汇编程序 gas 的正确语法,通常用于汇编 GCC 输出,第二个是nasm 汇编程序。