實驗四:使用庫函數API和C代碼中嵌入彙編代碼兩種方式使用同一個系統調用

賀邦+原創做品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000ubuntu

實驗目的:

使用庫函數API和C代碼中嵌入彙編代碼兩種方式使用同一個系統調用,理解系統調用的工做機制。安全

實驗過程:

本文實驗選擇24號和47號系統調用,分別獲取當前用戶uid(用戶ID)和gid(組ID),即模擬Linux系統「id」命令。
 

編寫兩段代碼,分別使用庫函數API和C代碼中嵌入彙編代碼,源碼以下:函數

uidgid.c(使用庫函數API方式):ui



程序中經過調用getuid()和getgid()函數來獲取當前執行用戶uid和gid操作系統

參考:《Advanced Programming in the UNIX Environment》指針

uidgid_asm.c(使用C代碼中嵌入彙編代碼方式):blog


內嵌彙編代碼版本源碼中將原來兩行經過API函數獲取uid和gid的代碼註釋掉,用匯編代碼替換。開發

首先將ebx寄存器清零,表示無參數傳入。get

而後分別將0x18和0x2f(十進制24和47)賦值給eax寄存器,表示須要調用的系統調用號,24爲getuid,47爲getgid。源碼

執行int 0x80來執行系統調用。

以後eax寄存器保存了返回值,將它分別賦值給輸出uid或gid變量。

完成整個彙編代碼的系統調用。

分別編譯兩個源碼文件、執行系統id命令以及兩個編譯好的程序


上面的截圖分別表示普通用戶ubuntu和管理員用戶root分別執行系統自帶命令id,庫函數API方式uidgid,內嵌彙編方式uidgid_asm這三種方式運行獲得的結果是同樣的。

實驗分析:

經過實驗執行結果可知,程序成功完成了系統調用獲取當前用戶uid和gid的操做,經過內嵌彙編代碼能夠清晰的看出調用系統調用的工做過程。

首先將ebx寄存器清零,表示無參數傳入。

而後分別將0x18和0x2f(十進制24和47)賦值給eax寄存器,表示須要調用的系統調用號,24爲getuid,47爲getgid。

執行int 0x80來執行系統調用。

以後eax寄存器保存了返回值,將它分別賦值給輸出uid或gid變量。

完成整個彙編代碼的系統調用。

在Linux系統中是經過激活0x80中斷來觸發系統調用的,須要調用的系統調用號實現賦值給eax存儲器,若是有傳入參數可賦值給ebx寄存器,若是多於1個則按順序賦值給ebx、ecx、edx、esi、edi、ebp,若是超過6個則經過指針變量指向另外一片堆棧區,若是無參數傳入則賦值爲0。

實驗總結:

雖然Intel X86 CPU有4種執行級別0~3,可是在Linux系統中僅使用了0和3級,分別表示內核態用戶態

一些涉及底層、硬件、核心的操做必須在內核態下才容許執行,爲操做系統程序和驅動程序專享,普通程序僅能執行在用戶態下。若是普通程序須要涉及內核態的操做,就須要經過系統調用來實現。這樣作的好處是屏蔽平臺相關操做下降了軟件開發難度,加強了系統安全性,使程序具備更好的移植性(Linux系統及其餘Unix系統遵循統一標準,系統調用基本同樣)。

相關文章
相關標籤/搜索