X86 Сборка: до создания системного вызова в Linux, если вы сохраняете все регистры?

У меня есть код ниже, который открывает файл, считывает его в буфер и затем закрывает файл.

Для закрытия файловой системы требуется, чтобы номер дескриптора файла находился в регистре ebx. Регистр ebx получает номер дескриптора файла до того, как будет выполнен системный вызов read. Мой вопрос в том, должен ли я сохранить регистр ebx в стеке или где-нибудь, прежде чем я сделаю системный вызов для чтения (может ли int 80h уничтожить регистр ebx?). А затем восстановите регистр ebx для закрытого системного вызова? Или код, который у меня ниже, безопасный?

Я запустил приведенный ниже код, и он работает, я просто не уверен, что он обычно считается хорошей практикой сборки или нет, потому что я не сохраняю регистр ebx перед вызовом чтения 8080.

;; 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         

Ответ 1

Сам вызов int 80h не повредит ничего, кроме размещения возвращаемого значения в eax. Итак, у вас есть фрагмент кода. (Но если ваш фрагмент кода является частью более крупной программы, которая, как ожидается, будет вызываться другим кодом, следуя обычным Linux x86 ABI, вам необходимо сохранить ebx и, возможно, другие регистры, при входе в вашу программу и восстановить при выходе.)

Соответствующий код в ядре можно найти в arch/x86/kernel/entry_32.S. Это связано с широким использованием макросов и различными подробностями (поддержка трассировки syscall, аннотации отладки DWARF и т.д.), Но: обработчик int 80h - system_call (строка 493 в версии, которую я использую связанный с); регистры сохраняются с помощью макроса SAVE_ALL (строка 497); и они снова восстанавливаются через RESTORE_REGS (строка 534) непосредственно перед возвратом.