He estado siguiendo el excelente libro Programming Ground Up, queriendo aprender ensamblaje. Aunque no estaba en el libro en este momento, quería llamar a mi función de ensamblaje desde C. en una máquina de 32 bits, esto funciona igual que cuando se trabaja desde el libro.C to assembly call convention 32bit vs 64bit
Lo que hago aquí es almacenar el primer argumento en %ebx
y el segundo en %ecx
.
.type power, @function
.globl power
power:
pushq %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
Compilo esto (y el resto de la función) en un fichero objeto, se crea una main.c, donde prototipo de la función y la llamo, algo como esto:
int power(int b, int x);
int a = power(2, 1);
Sin embargo Cuando compilo esto en una máquina de 64 bits, obtengo algunos resultados muy inesperados. Modifiqué lo obvio, como el hecho de que %esp
y %epb
deben ser reemplazados por %rsp
y %rpb
, ¡pero al excavar con GDB se revela que los argumentos no se encuentran en la pila!
Revisando lo que sucede al usar la opción -S
en GCC, puedo ver que en lugar de presionar las variables en la pila, GCC almacena los argumentos en los registros.
movl $1, %esi
movl $2, %edi
call power
En la máquina de 32 bits, que hace lo que espero y empujar los argumentos en la pila:
movl $1, 4(%esp)
movl $2, (%esp)
call power
Ahora lo que está pasando aquí? ¿Por qué GCC pasa los argumentos en registros en 64 bits y en la pila en 32 bits? ¡Esto es muy confuso! Y no puedo encontrar ninguna mención sobre esto en ningún lado. ¿Hay alguien que pueda iluminarme en esta situación?
convenciones de llamada x64 son diferentes a las x86. En la mayoría de los casos, debido a los registros adicionales, los primeros cuatro argumentos se pasan en los registros. – wj32