Actualmente estoy tratando de llamar a una función C genérica desde el ensamblaje en línea de GCC (mala idea, lo sé, pero estoy aburrido hoy ...).Ensamblaje en línea de GCC - Mover float a XMM0 antes de llamar a
Mi sistema operativo es Mac OS X, 64bits, por lo que la convención de llamada es System V, es decir, argumentos 0-6 se pasan a través de los rdi
, rsi
, rdx
, rcx
, r8
y r9
registros. Otros argumentos son empujados a la pila.
Conozco la firma de la función, así que puedo adivinar el tipo de devolución y el tipo de los argumentos. Con esa información, puedo colocar los argumentos en los registros correctos.
Todo funciona muy bien con tipos enteros, pero tengo un problema con los valores de coma flotante.
Los valores de punto flotante se deben pasar a través de los registros xmm0
- xmm7
.
El problema es básicamente el siguiente. Tengo una variable C del tipo float
. Necesito mover esa variable en, digamos, el registro xmm0
, usando el ensamblado en línea de GCC.
imaginar el siguiente código:
#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;
}
La función foo
se llama, con 42 como parámetro. Funciona ...
Ahora intento lo mismo con un argumento flotante. Solo tengo que usar movss
en lugar de mov
, y funciona.
El problema viene cuando intento llamar a dos funciones:
#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;
}
La función de tomar el argumento de flotación recibir 0. No entiendo por qué. que no toque la pila, así que no hay que hacer la limpieza ...
Si llamo a las funciones directamente desde C, GCC produce lo siguiente:
movl $42, -4(%rbp)
movl $0x42280000, %eax
movl %eax, -8(%rbp)
movl -4(%rbp), %edi
call _foo
movss -8(%rbp), %xmm0
call _bar
No entiendo la diferencia ... Cualquier ayuda será muy apreciada:)
tenga un buen día, todo
EDITAR
a lo solicitado, aquí está la salida ASM cuando se utiliza ensamblado en línea:
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
Conforme a lo solicitado, aquí está la salida 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>
Publique el asm generado por 'gcc' (use' gcc -S '). –
La parte importante ya está en la parte inferior de la publicación. Dime si necesitas algún otro código ...:) Gracias – Macmade
Pensé que el ensamblaje en la parte inferior de la publicación es lo que generó gcc al usar C para llamar a 'foo()' y 'bar()'. Lo que me gustaría ver es lo que genera gcc cuando usa el ensamblado en línea para llamar a esas funciones. –