2010-04-24 15 views
11

Tengo el siguiente código que abre un archivo, lo lee en un búfer y luego cierra el archivo.x86 Montaje: antes de realizar una llamada al sistema en Linux ¿Debería guardar todos los registros?

La llamada del sistema de archivo cerrado requiere que el número de descriptor de archivo esté en el registro de ebx. El registro ebx obtiene el número de descriptor de archivo antes de realizar la llamada al sistema de lectura. Mi pregunta es si debo guardar el registro ebx en la pila o en algún lugar antes de hacer la llamada al sistema de lectura, (¿podría int 80h trash el registro ebx?). ¿Y luego restaurar el registro de ebx para la llamada de cierre del sistema? ¿O es el código que tengo a continuación bien y seguro?

he ejecutar el código de abajo y funciona, es que no estoy seguro si se considera generalmente una buena práctica montaje o no porque no guarda el registro EBX antes de la llamada de lectura int 80h.

;; open up the input file 
mov eax,5  ; open file system call number 
mov ebx,[esp+8] ; null terminated string file name, first command line parameter 
mov ecx,0o  ; access type: O_RDONLY 
int 80h   ; file handle or negative error number put in eax 
test eax,eax 
js Error   ; test sign flag (SF) for negative number which signals error 

;; read in the full input file 
mov ebx,eax   ; assign input file descripter 
mov eax,3    ; read system call number 
mov ecx,InputBuff  ; buffer to read into 
mov edx,INPUT_BUFF_LEN ; total bytes to read 
int 80h 
test eax,eax 
js Error    ; if eax is negative then error 
jz Error    ; if no bytes were read then error 
add eax,InputBuff  ; add size of input to the begining of InputBuff location 
mov [InputEnd],eax  ; assign address of end of input 

;; close the input file 
;; file descripter is already in ebx 
mov eax,6  ; close file system call number 
int 80h   
+0

sugerencia: Haga una prueba para que el resultado de la lectura sea '<= 0 'en la ruta rápida, luego resuélvala en' Error '. Eso reduce la cantidad de entradas de historial de predicción de bifurcación que su código normalmente necesita. 'jle' funcionará, porque' test eax, eax' borra el desbordamiento y lleva las banderas, y establece SF y ZF de acuerdo con el resultado de la misma manera que 'cmp eax, 0'. –

Respuesta

11

La llamada int 80h misma voluntad no corrupta nada, aparte de poner el valor de retorno en eax. Entonces el fragmento de código que tienes está bien. (Pero si el fragmento de código es parte de una rutina más grande que se espera sea invocada por otro código siguiendo el habitual Linux x86 ABI, deberá conservar ebx, y posiblemente otros registros, al ingresar a su rutina, y restaurar a la salida .)

El código correspondiente en el kernel se puede encontrar en arch/x86/kernel/entry_32.S. Es un poco difícil de seguir, debido al uso extensivo de macros, y varios detalles (soporte para rastreo de syscall, anotaciones de depuración DWARF, etc.) pero: el controlador int 80h es system_call (línea 493 en la versión que he vinculado); los registros se guardan a través de la macro SAVE_ALL (línea 497); y se restablecen nuevamente a través del RESTORE_REGS (línea 534) justo antes de regresar.

+0

En general, de acuerdo con 'syscall (2)', "algunas arquitecturas pueden interceptar indiscriminadamente otros registros que no se enumeran aquí". Específicamente, las llamadas al sistema x86-64 (hechas con 'syscall') * do * clobber' rcx' y 'r11', de acuerdo con mi lectura de [este informe de entry_64.S] (https://github.com/0xAX/ linux-insides/blob/master/SysCall/syscall-2.md). Esto está respaldado por el hecho de que la instrucción 'sysret' (utilizada por entry_64.S) hace' RIP = RCX', y 'RFLAGS = R11', y algunas cosas del segmento. Vuelve al modo de usuario después de ejecutarlo. ** AFAICT, x86-64 syscalls preservan todo, excepto R11, RCX y RAX **. –

+0

No pude encontrar ninguna documentación específica, o incluso comentarios en el código, indicando la situación exacta de amd64 o i386. Creo que es extraño que quede un punto importante como ese para que los lectores puedan descifrar las macros. En la práctica, me refiero a que solo los implementadores de libc necesitan esa información, pero dado el compromiso de Linux de mantener un ABI estable, no espero que cambie alguna vez. Entonces podría ser anotado. (Y supongo que sí, aquí, así que subí: P) –

+0

Actualizar sí, 'syscall' en sí mismo clobbers RCX/R11, y [Llamadas al sistema Linux hechas usando' syscall' solo clobber those + 'rax'] (https: // stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-i386-and-x86-6). Pero IIRC, fue mi edición que incluyó eso; No recuerdo si alguna vez encontré documentación externa que no sea el código fuente de Linux para esto. –

Cuestiones relacionadas