1.系統調用和普通函數完全不同,系統調用實際上是0x80号中斷對應的中斷處理程式的子程式。換句話說,在linux系統上,0x80中斷是系統調用的統一入口。某個具體的系統調用是這個中斷處理程式的子程式,進入具體某個系統調用是通過核心定義的系統調用号碼來實作的。linux通過執行如下彙編代碼陷入核心執行系統調用:
int 0x80; //這一句是進入系統調用統一入口。
2.每個系統調用在核心裡面都對應一個号碼,這個号碼是在/usr/include/i386-linux-gnu/asm/unistd_32.h中定義的。如下圖,圖1所示

圖1 核心定義系統調用号碼
在執行"int 0x80;"進行中斷之前,應用層會做如下準備工作:
1.把系統調用号碼指派給寄存器EAX;
2.把系統調用需要的參數按次序指派給寄存器EBX,ECX,EDX等等。
這樣,等下0x80中斷發生的時候,系統調用需要的全部資訊就能通過這些寄存器傳遞給中斷處理程式了。
注:實際上系統調用需要的參數也可以使用應用程式的棧傳入核心。稍後實驗環節可以看到,這個不用太糾結。
如下圖圖2:
圖2 系統調用執行流程
原型:
ssize_t write(int fd, const void *buf, size_t count);
例子:
write(1,"abc\n",5); //往螢幕上列印"abc\n"。注意,buf裡面是5個字元,第5個是字元串結尾0
1.根據/usr/include/i386-linux-gnu/asm/unistd_32.h的宏定義,我們可以得出write()在linux上的系統調用号是4;
2.write()需要3個參數;
3.在應用層,把系統調用号4賦給EAX。
movl $4, (%eax);
4.在應用層,把fd(1是螢幕輸出)賦給EBX。
movl $1, %ebx;
5.在應用層,把buf首位址賦給ECX。
movl $.LC0, %ecx (下面實驗環節可看到$.LC0對應buf首位址);
6.在應用層,把buf攜帶的有效資料長度賦給EDX。
movl $5, %edx;
7.陷入核心,進入系統調用統一入口。
int $0x80;
8.核心執行write()系統調用;
9.系統調用傳回。
1.原始C程式
圖3 write.c
C程式執行結果,如圖4
圖4
2.使用gcc将C程式編譯為彙編
gcc -S write.c
會生成write.s,彙編内容如圖5
圖5 write.s
直接編譯write.s,生成a.out,并執行。如圖6
圖6
3. 現在我們自己寫一個彙編mywrite.s,執行write系統調用。
彙編内容如圖7
圖7 mywrite.s
mywrite.s編譯後執行結果,如圖8
圖8
現在,我們成功使用int 0x80進行了系統調用。