Сборка x86: перед системным вызовом в Linux, следует ли сохранять все регистры? - PullRequest
11 голосов
/ 24 апреля 2010

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

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

Я запустил приведенный ниже код, и он работает, я просто не уверен, считается ли это хорошей практикой сборки или нет, потому что я не сохраняю регистр ebx до вызова чтения 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         

Ответы [ 2 ]

11 голосов
/ 25 апреля 2010

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

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

1 голос
/ 24 апреля 2010

Да, вы должны сохранить и восстановить как в http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/040/4048/4048l1.html

...