В настоящее время я пытаюсь вызвать универсальную функцию C из встроенной сборки GCC (я знаю, что это плохо, но сегодня мне скучно ...).
Моя операционная система - Mac OS X,64 бита, поэтому соглашение о вызовах - это System V, то есть аргументы 0-6 передаются через регистры rdi
, rsi
, rdx
, rcx
, r8
и r9
.Другие аргументы помещаются в стек.
Я знаю сигнатуру функции, поэтому могу угадать тип возвращаемого значения и тип аргументов.С помощью этой информации я могу поместить аргументы в правильные регистры.
Все отлично работает с целочисленными типами, но у меня возникла проблема со значениями с плавающей запятой.
Должны быть значения с плавающей запятойпрошел через регистры xmm0
- xmm7
.
Таким образом, проблема в основном заключается в следующем.У меня есть переменная C типа float
.Мне нужно переместить эту переменную, скажем, в регистр xmm0
, используя встроенную сборку GCC.
Представьте себе следующий код:
#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;
}
Вызвана функция foo
,с 42 в качестве параметра.Это работает ...
Теперь я пытаюсь сделать то же самое с аргументом float.Мне нужно только использовать 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получить 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 при использовании встроенной сборки:
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
По запросу, вот вывод 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>