I'm currently trying to call a generic C function from within the GCC built-in assembly (a bad idea, I know, but I'm bored today ...).
My operating system is Mac OS X, 64 bit, so the calling convention is System V, that is, arguments 0-6 are passed through rdi , rsi , rdx , rcx , r8 and r9 . Other arguments are pushed onto the stack.
I know the signature of the function, so I can guess the return type and argument type. With this information, I can put the arguments in the correct registers.
Everything works fine with integer types, but I am having a problem with floating point values.
Floating point values ββmust go through the registers xmm0 - xmm7 .
Thus, the problem is mainly as follows. I have a C variable of type float . I need to move this variable into, say, the xmm0 register using the built-in GCC assembly.
Provide the following code:
#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; }
The foo function is called with parameter 42. It works ...
Now I try the same with the float argument. I need to use movss instead of mov , and it works.
The problem occurs when I try to call both functions:
#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; }
A function that takes a float argument takes 0. I donβt understand why. I do not touch the stack, so there is no cleaning ...
If I call functions directly from C, GCC creates the following:
movl $42, -4(%rbp) movl $0x42280000, %eax movl %eax, -8(%rbp) movl -4(%rbp), %edi call _foo movss -8(%rbp), %xmm0 call _bar
I do not understand ... Any help would be greatly appreciated :)
Good day everyone
EDIT
As requested, ASM is issued using the built-in assembly:
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;
EDIT2
As requested here, the output of GDB:
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>