【发布时间】:2021-04-06 22:09:56
【问题描述】:
我想知道,根据实际指令读取输入变量是否有限制?
我正在尝试为 .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");
}
返回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 混淆了,它们不代表相同的操作吗?
任何帮助将不胜感激。
【问题讨论】:
-
.rept是对汇编器重复代码的指令。它不会使用您使用"m"指定的内存引用。编译器可能会将内存引用写成-4(%rbp)之类的东西,因此会出现有关负值的错误消息。我不认为 GCC 或 Clang 对此有限制。您可以将"i"用于立即操作数,但它带有表示指令中立即操作数的标记,在英特尔程序集中使用$,因此它将$42放入程序集中,而您需要一个普通的@987654338 @。可能没有办法做到这一点。 -
您不能在
asm()语句中安全地使用ret,除非作为__attribute__((naked))函数主体的一部分。 (在这种情况下,整个主体必须是基本 Asm 语句;没有输入/输出约束。即,这是一种让编译器在您用 asm 编写整个函数主体时进行名称修改的方法。)除此之外,您不能ret;当编译器将您的函数内联到某个调用者时,这将中断。 -
这很有意义。查看
int function()的反汇编,可以看出[rbp-0x4]确实是内存引用的产物。非常感谢 Eric 的解释。 -
哦,哇,谢谢你指出彼得!确实,我只是尝试从
main()返回function()的返回值,然后一切都崩溃了。 -
类似地,如果您在扩展的
asm语句中写入寄存器,则需要将其作为clobber 或输出操作数提及。即在编译器的脚趾上编写 EAX 步骤的 asm,你应该预料到会损坏。
标签: c gcc inline-assembly