它将var mem地址与eax寄存器值相加var值。
是的,gcc内联汇编的语法非常神秘。来自GCC Inline Assembly HOWTO"m"
中的相关部分的释义粗略地给出了C变量的内存位置。
这就是你想要的地址,你可以写或读的地方。注意我说的是变量的位置,所以%0
设置为Word32 *var
的地址 - 你有一个指向指针的指针。内联汇编块的C语言翻译看起来像EAX += *(&var)
,因为您可以说"m"
约束隐含地使用C变量的地址,并为您提供地址表达式,然后将其添加到%eax
。
有没有什么办法告诉addl指令使用var值而不是将var mem地址复制到寄存器?
这取决于你的意思。你需要从堆栈中得到var
,所以有人提领内存(请参阅@Bo Perssons答案),但你没有做内联汇编
约束必须"m"(*var)
(如@fazo建议)。这会给你的内存位置的值var
指向的是,而不是指向它的内存位置。
生成的代码现在是:
test_func:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
#APP
# 2 "test.c" 1
addl (%eax), %eax
# 0 "" 2
#NO_APP
popl %ebp
ret
这是一个小犯罪嫌疑人,但是这是可以理解的,你忘了告诉GCC,你打一顿(修改,而无需输入/输出列表)%eax
。修复是asm("addl %0, %%eax" : : "m"(*var) : "%eax")
产生:
movl 8(%ebp), %edx
addl (%edx), %eax
这是不是在这个情况任何更好或更正确,但它始终是一个很好的做法记住。请参阅clobber list上的章节,并特别注意"memory"
clobber的高级使用内联汇编。
即使你不想(明确地)将内存地址加载到寄存器中,我会简要地介绍它。 从"m"
更改约束"r"
几乎似乎工作,有关章节得到改变到(如果包括在撞列表%eax
):
movl 8(%ebp), %edx
addl %edx, %eax
这几乎是正确的,我们已经加载的指针值var
成一个注册表,但现在我们必须指定我们正在从内存加载。改变代码相匹配的约束(通常不希望的,我只显示它的完整性):
asm("addl (%0), %%eax" : : "r"(var) : "%eax");
给出:
movl 8(%ebp), %edx
addl (%edx), %eax
同样作为与"m"
。
你的内联汇编没有定义什么是应该是在EAX,所以GCC可以把任何那里...你居然想干什么? – servn