¿Se requiere asmlinkage para llamar a una función c desde el ensamblado?

¿Se requiere asmlinkage para llamar a una función c desde el ensamblado?


Estoy escribiendo una función C que se invocará desde el código ensamblador.


(Específicamente, quiero hacer un trabajo de verificación en la ruta del manejo de llamadas al sistema en el kernel de Linux, así que llamaré a la función c antes de que se envíe una llamada al sistema en entry_32.S)


Estoy confundido con el modificador "asmlinkage" al definir mi función c.


Sé que asmlinkage es para decirle al compilador que los parámetros se pasarán a través de la pila.


#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))


Preguntas:


(1) ¿Se requiere asmlinkage al definir una función de este tipo que se invocará desde el código ensamblador?


(2) cuál es la convención de llamadas predeterminada en gcc. Si omito "asmlinkage" al definir una función c, ¿implica _cdecl o fastcall?


(3) si la convención de llamada predeterminada es cdecl, ¿por qué se necesita asmlinkage, considerando que cdecl es igual al modificador asmlinkage? (¿Estoy en lo correcto aquí?)


(4) ¿Por qué todas esas funciones de llamada al sistema se declaran con asmlinkage? ¿Podemos copiar los parámetros a los registros primero y luego llamar a esas funciones de llamada al sistema? Desde mi punto de vista, en x86, al emitir una llamada al sistema, los parámetros se guardan fácilmente en los registros; entonces, ¿por qué molestarse en guardarlos en la pila para hacer cumplir dichos parámetros de paso a través de la convención de la pila?


Finalmente, ¿alguien puede recomendar algunos recursos/libros a los que pueda referirme para tal programación mixta de ensamblaje/c?


Respuestas:


Después de varias horas de investigación, obtuve los siguientes puntos empíricos:


(1) ¿Se requiere asmlinkage al definir una función de este tipo que se invocará desde el código ensamblador?


No. En realidad, la llamada rápida se usa con frecuencia.


Por ejemplo, en entrada_32.S, si busca "llamar", puede obtener todas las funciones c invocadas desde este archivo de ensamblado. Entonces puede ver que muchos usan fastcall en lugar de asmlinkage como convención de llamadas. Por ejemplo,


    /*in entry_32.S*/
movl PT_OLDESP(%esp), %eax
movl %esp, %edx
call patch_espfix_desc
/*in traps_32.c*/
fastcall unsigned long patch_espfix_desc(unsigned long uesp,
unsigned long kesp)

(2) ¿Cuál es la convención de llamadas predeterminada en gcc? Si omito "asmlinkage" al definir una función c, ¿implica _cdecl o fastcall?


(3) si la convención de llamada predeterminada es cdecl, ¿por qué se necesita asmlinkage, considerando que cdecl es igual al modificador asmlinkage? (¿Estoy en lo correcto aquí?)


Para las funciones de C que no se invocan desde el código ensamblador, podemos suponer con seguridad que la convención de llamada predeterminada es cdecl (o llamada rápida; no importa, porque gcc se encargará de la persona que llama y del receptor de la llamada para el paso de parámetros. La convención de llamada predeterminada puede ser especificado al compilar). Sin embargo, para las funciones de C invocadas desde el código ensamblador, debemos declarar explícitamente la convención de llamada de la función, porque el código de paso de parámetros en el lado ensamblador se ha corregido. Por ejemplo, si patch_espfix_desc se declara como asmlinkage, gcc compilará la función para recuperar los parámetros de la pila. Esto es inconsistente con el lado ensamblador, que coloca los parámetros en registros.


Pero todavía no tengo claro cuándo usar asmlinkage y cuándo usar fastcall. Realmente necesito algunas pautas y recursos a los que referirme.