В настоящее время я пытаюсь вызвать общую функцию C из встроенной сборки GCC (я знаю, плохая идея, но мне сегодня скучно ...).
Моя операционная система - Mac OS X, 64 бита, поэтому соглашение о вызовах - System V, то есть аргументы 0-6 передаются через регистры rdi
, rsi
, rdx
, rcx
, r8
и r9
. Остальные аргументы помещаются в стек.
Я знаю сигнатуру функции, поэтому могу угадать возвращаемый тип и тип аргументов. Обладая этой информацией, я могу поместить аргументы в правильные регистры.
Все отлично работает с целочисленными типами, но у меня проблема со значениями с плавающей запятой.
Значения с плавающей запятой необходимо передавать через регистры _7 _-_ 8_.
Итак, проблема в основном в следующем. У меня есть переменная 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. Оно работает...
Теперь я пробую то же самое с аргументом с плавающей запятой. Мне нужно только использовать 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;
}
Функция, принимающая аргумент с плавающей запятой, получает 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;
РЕДАКТИРОВАТЬ2
Как и просили, вот вывод 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>
gcc
(используйтеgcc -S <whatever>
). - person Michael Burr   schedule 02.05.2011foo()
иbar()
. Я бы хотел увидеть, что генерирует gcc, когда вы используете встроенную сборку для вызова этих функций? - person Michael Burr   schedule 02.05.20110x42280000
вxmm0
(хотя я не знаю, почему он предпринимает дополнительные шаги, чтобы сделать это через-4(%rbp)
) - мне пришлось бы пройти через это с помощью отладчика, чтобы увидеть, что мне не хватает, что установкаxmm0
на ноль. К сожалению, на данный момент у меня нетgcc
, ориентированного на x64. Вы пробовали пройти через сборку вgdb
, чтобы увидеть, где что-то не так? - person Michael Burr   schedule 02.05.2011