繁体   English   中英

GCC 内联汇编 - 调用前将浮点数移动到 XMM0

[英]GCC inline assembly - Move float to XMM0 before call

我目前正在尝试从 GCC 内联程序集调用通用 C function (坏主意,我知道,但我今天很无聊)。

我的操作系统是 64 位的 Mac OS X,所以调用约定是 System V,这意味着 arguments 0-6 通过rdirsirdxrcxr8r9寄存器传递。 其他 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM