Gcc 无疑问
我试图了解Linux中内联汇编程序的一些内容。我正在使用以下功能:Gcc 无疑问,gcc,assembly,Gcc,Assembly,我试图了解Linux中内联汇编程序的一些内容。我正在使用以下功能: void test_func(Word32 *var){ asm( " addl %0, %%eax" : : "m"(var) ); return; } 它生成以下汇编代码: .globl test_func .type test_func, @function test_func: pushl %ebp movl %esp, %ebp #APP # 336 "opers.c"
void test_func(Word32 *var){
asm( " addl %0, %%eax" : : "m"(var) );
return;
}
它生成以下汇编代码:
.globl test_func
.type test_func, @function
test_func:
pushl %ebp
movl %esp, %ebp
#APP
# 336 "opers.c" 1
addl 8(%ebp), %eax
# 0 "" 2
#NO_APP
popl %ebp
ret
.size test_func, .-test_func
它将var mem地址和eax寄存器值相加,而不是var值
有没有办法告诉addl指令在不将var mem地址复制到寄存器的情况下使用var value而不是var mem address
问候是的,因为你给了他一个var,即地址。给他 比如: 我记不清了,但你应该把“m”换成“r”
内存操作数不存在;这并不意味着它将从该地址获取价值。它只是一个指针不,x86处理器没有两级间接寻址模式
您必须首先从内存地址加载指针,然后从指针间接加载。它将var mem地址和eax寄存器值相加,而不是var值。 是的,gcc内联程序集的语法相当神秘。从
“m”
中的相关部分进行解释,大致给出C变量的内存位置
当你只需要一个可以写或读的地址时,你会使用它。注意我说的是C变量的位置,所以%0
被设置为Word32*var
的地址-您有一个指向指针的指针。内联程序集块的C转换可能看起来像EAX+=*(&var)
,因为您可以说“m”
约束隐式获取C变量的地址,并为您提供一个地址表达式,然后将其添加到%EAX
有没有办法告诉addl指令使用var value而不是var mem address,而不将var mem address复制到寄存器中?
那要看你的意思了。您需要从堆栈中获取var
,因此必须有人取消对内存的引用(请参见@Bo Perssons answer),但您不必在内联汇编中执行此操作
约束必须是“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,以了解内联程序集的高级用法
即使您不想(显式地)将内存地址加载到寄存器中,我也将简要介绍一下。
将约束从“m”
更改为“r”
似乎几乎可行,相关部分将更改为(如果我们将%eax
包括在clobber列表中):
这几乎是正确的,我们已经将指针值var
加载到一个寄存器中,但是现在我们必须指定从内存加载的指针值。更改代码以匹配约束(通常不受欢迎,我只是为了完整性而展示):
给出:
movl 8(%ebp), %edx
addl (%edx), %eax
与“m”相同
试试看
void test_func(Word32 *var){
asm( " mov %0, %%edx; \
addl (%%edx), %%eax" : : "m"(var) );
return;
}
这样做将用var地址覆盖%eax值以获取var值。您的内联asm没有定义eax中应该包含的内容,因此gcc可以将任何内容放在那里。。。你到底想做什么?
asm("addl (%0), %%eax" : : "r"(var) : "%eax" );
movl 8(%ebp), %edx
addl (%edx), %eax
void test_func(Word32 *var){
asm( " mov %0, %%edx; \
addl (%%edx), %%eax" : : "m"(var) );
return;
}