[英]GCC inline assembly - Move float to XMM0 before call
我目前正在尝试从 GCC 内联程序集调用通用 C function (坏主意,我知道,但我今天很无聊)。
我的操作系统是 64 位的 Mac OS X,所以调用约定是 System V,这意味着 arguments 0-6 通过rdi
、 rsi
、 rdx
、 rcx
、 r8
和r9
寄存器传递。 其他 arguments 被推入堆栈。
我知道 function 签名,所以我可以猜测返回类型,以及 arguments 的类型。 有了这些信息,我可以将 arguments 放在正确的寄存器中。
integer 类型一切正常,但浮点值有问题。
浮点值需要通过xmm0
- xmm7
寄存器传递。
所以问题基本上如下。 我有一个float
类型的 C 变量。 我需要使用 GCC 的内联汇编将该变量移动到xmm0
寄存器中。
想象一下下面的代码:
#include <stdio.h>
void foo( int x )
{
printf( "X: %i\n", x );
}
int main( void )
{
int x = 42;
__asm__
(
"mov %[x], %%rdi;"
"call _foo;"
:
: [ x ] "m" ( x )
);
return 0;
}
调用 function foo
,参数为 42。 有用...
现在我尝试使用浮点参数进行相同的操作。 我只需要使用movss
而不是mov
,它就可以工作。
当我尝试调用这两个函数时,问题就来了:
#include <stdio.h>
void foo( int a )
{
printf( "A: %i\n", a );
}
void bar( float b )
{
printf( "B: %f\n", b );
}
int main( void )
{
int a = 42;
float b = 42;
__asm__
(
"mov %[a], %%rdi;"
"call _foo;"
"movss %[b], %%xmm0;"
"call _bar;"
:
: [ a ] "m" ( a ),
[ b ] "m" ( b )
);
return 0;
}
采用 float 参数的 function 接收 0。我不明白为什么。 我不碰堆栈,所以没有清理工作要做......
如果我直接从 C 调用函数,GCC 会产生以下结果:
movl $42, -4(%rbp)
movl $0x42280000, %eax
movl %eax, -8(%rbp)
movl -4(%rbp), %edi
call _foo
movss -8(%rbp), %xmm0
call _bar
我不明白...任何帮助将不胜感激:)
祝大家有个愉快的一天
编辑
根据要求,这是使用内联汇编时的 ASM output:
movl $42, -4(%rbp)
movl $0x42280000, %eax
movl %eax, -8(%rbp)
mov -4(%rbp), %rdi;
call _foo;
movl -8(%rbp), %eax;
movl %eax, -4(%rbp);
movss -4(%rbp), %xmm0;
call _bar;
编辑2
根据要求,这是 GDB output:
0x100000e9e <main+4>: movl $0x2a,-0x4(%rbp)
0x100000ea5 <main+11>: mov $0x42280000,%eax
0x100000eaa <main+16>: mov %eax,-0x8(%rbp)
0x100000ead <main+19>: mov -0x4(%rbp),%rdi
0x100000eb1 <main+23>: callq 0x100000e54 <foo>
0x100000eb6 <main+28>: movss -0x8(%rbp),%xmm0
0x100000ebb <main+33>: callq 0x100000e75 <bar>
我花了一段时间,但我想通了。 在使用内联汇编的 output 中,gcc 使用rbp
的负偏移量来存储值。 但是,由于它不知道内联汇编中的 function 调用,因此它认为它不会调用任何函数。 因此,它将变量放在红色区域中,并且不会更改rsp
以为变量腾出空间。 当你调用 foo 时,返回地址被压入堆栈,覆盖你存储的变量并给你一个不正确的变量。
如果在程序集外部的主 function 中的任何一点,您调用了 function,那么 gcc 将更改堆栈以保留变量。 例如,如果您添加foo(-1);
到主要的顶部,它会起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.