呼叫"系統呼叫函式write"的兩種實現
我們知道呼叫“系統呼叫”有兩種方式。
( 1) 將系統呼叫指令封裝為 c庫函式,通過庫函式進行系統呼叫,操作簡單。
(2)不依賴任何庫函式,直接通過彙編指令 int與作業系統通訊。
我們平常寫的C語言用的就是第一種系統呼叫,通過函式呼叫write函式,我們下面用匯編語言來重寫一下,利用我們定義的simu_write函式來更好的探究write函式的運作機理
syscall.S
section .data str_c_lib: db "c library says: hello world",0xa str_c_lib_len equ $-str_c_lib section .text global _start _start: ;;;模擬c語言;; push str_c_lib_len push str_c_lib push 1 ;是push到標準輸出,也是一個引數 call simu_write add esp,12 ;;;退出程式,不然會出現段錯誤;; mov eax,1 int 0x80 simu_write: push ebp mov ebp,esp mov eax,4 mov ebx,[ebp+8] mov ecx,[ebp+12] mov edx,[ebp+16] int 0x80 pop ebp ret
我們簡單的來解釋一下這一種方法:其先通過函式呼叫約定,從右向左往棧中壓入引數str_c_lib_len,str_c_lib,1,(write(1,str_c_lib,str_c_lib_len))然後呼叫simu_write函式
在我們的simu_write函式中先儲存舊的ebp,然後呼叫第4號子功能:write系統呼叫,將其存放在eax中,然後分別放入引數。這裡也就是我們所說的第二種系統呼叫了,不過我們先不在這裡說,在下一個程式中說。
完成這些後,通過
mov eax,1
int 0x80
退出程式。其中第1號子功能是exit
int 0x80 發起中斷,通知 Linux完成請求的功能,即完成退出請求
好,讓我們來看第二種方法,繞過庫函式,直接與OS通訊
預備知識:
系統呼叫輸入引數的傳遞方式:
當輸入的引數小於等於 5 個時, Linux 用暫存器傳遞引數。當引數個數大於 5 個時,把引數按照順序 放入連續的記憶體區域,並將該區域的首地址放到 ebx 暫存器。這裡我們只演示引數小於等於 5 個的情況。 eax暫存器用來儲存子功能號(暫存器 eip、 ebp、 esp是不能使用的)。 5個引數存放在以下暫存器中,
傳送引數的順序如下。
(1) ebx儲存第 1個引數。
(2) ecx儲存第 2個引數。
(3) edx儲存第 3個引數。
(4) esi儲存第 4個引數。
(5) edi儲存第 5個引數。
程式如下:
section .data
str_syscall: db "syscall says: hello world!",0xa
str_syscall_len equ $-str_syscall
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,str_syscall
mov edx,str_syscall_len
int 0x80
mov eax,1
int 0x80
是不是發現不用庫函式,直接進行系統呼叫很簡單呢~嘻嘻,我們今天就到此為止了