
Deint80h.org, el tutorial sobre lenguaje ensamblador de FreeBSD
La convención [Linux Calling] tiene una gran desventaja sobre la forma Unix, al menos en lo que respecta a la programación en lenguaje ensamblador: cada vez que realiza una llamada al kernel debe presionar los registros y luego abrirlos más tarde. Esto hace que su código sea más voluminoso y lento.
Continúa diciendo que FreeBSD admite tanto la convención de Linux como la "Convención de Unix".
Si está codificando específicamente para FreeBSD, siempre debe utilizar la convención de Unix: es más rápido, puede almacenar variables globales en registros, no tiene que marcar el ejecutable y no impone la instalación del paquete de emulación de Linux en el sistema objetivo.
Me parece extraño que el sistema Linux sea más voluminoso y lento. Parece que hay dos opciones,
- Guarde sólo los registros que necesita conservar, que son
- esos registros volátiles que pueden ser afectados por la llamada al sistema (que yo sepa
ecx
) - o bien, los registros necesarios para enviar los argumentos apropiados al núcleo para realizar el
syscall
(que puede sereax
,ecx
,edx
,esi
,edi
,ebp
)
- esos registros volátiles que pueden ser afectados por la llamada al sistema (que yo sepa
- Guarde el 100% de los argumentos del kernel en la pila.
Parecería que el de FreeBSD es elel peorEscenario de caso de la convención de Linux. ¿Qué me estoy perdiendo? ¿Cómo es que la convención FreeBSD (que ellos llaman el "método Unix") es menos voluminosa y más rápida?
Respuesta1
En mi opinión, esto realmente se reduce a la opinión del autor.
En la convención de FreeBSD (“Unix”), usted inserta los argumentos en la pila, especifica el número de llamada del sistema en EAX
e invoca la interrupción 0x80 (con un operando adicional en la pila porque espera ser llamado desde una función separada).
En la convención Linux i386, coloca los argumentos en los registros apropiados e invoca la interrupción 0x80.
El argumento voluminoso/lento presumiblemente proviene del hecho de que con la convención de Linux, elllamadornecesita lidiar con el uso de registros. Si la llamada al sistema necesita argumentos en registros que contienen valores que le interesan a la persona que llama, necesita preservarlos, lo que resulta en trabajo preliminar adicional;vea este ejemplo de la biblioteca C. En este ejemplo, la llamada al sistema necesita valores en EAX, EBX, EDX, EDI y ESI; pero a la persona que llama solo le importa preservar EBX, EDI y ESI, por lo que solo los envía a la pila. El caso general esbastante mas complejo(pero ese también es el resultado de tratar con una mezcla de C y lenguaje ensamblador, tratando de generar código óptimo en todos los casos), sin embargo, al escribir en lenguaje ensamblador, que es el punto del sitio al que te refieres, eso no sería No será un gran problema.
Me parece que son seis y media docena: en la convención de FreeBSD, empujas a la pila en todos los casos, en la convención de Linux, empujas a la pila (o en cualquier otro lugar) dependiendo de lo que estés haciendo. el sitio de la llamada. Se podría argumentar que la convención de Linux permite un código más rápido ya que puede realizar todos los cálculos en registros... ComoRobarseñala, sin embargo, que en Linux los registros aún terminan siendo enviados (para construir la struct pt_regs
instancia que se utiliza para proporcionar los argumentos a las funciones C que se ocupan de las llamadas al sistema), por lo que el costo total es mayor en el lado de Linux que en el Lado de FreeBSD.
En cualquier caso, discutir sobre el rendimiento cuando se habla de código basado en pila o registro en torno a una llamada al sistema parece bastante pedante, dado el costo de realizar la llamada al sistema en sí. Cualquier ciclo salvado es, por supuesto, bueno en términos absolutos, pero la mejora relativa será mínima.