天天看點

用asm内聯彙編實作系統調用1 系統調用的概念2 用asm實作系統調用的執行個體3 小結

原創内容(cxsmarkchan 陳曉爽)

轉載請注明出處

《Linux核心分析》MOOC課程學習筆記

為保證系統的穩定運作,CPU運作狀态被分為核心态和使用者态。作業系統在核心态下運作,是以擁有所有計算機資源的操作權限。而一般的應用程式則在使用者态下運作,它們不能直接操作底層的硬體裝置,進而保證應用軟體不會破壞系統的穩定。但是,應用程式在運作時常常需要和各種資源打交道,為此,作業系統提供了“系統調用”的功能,提供一組API,由使用者态程式調用。本文通過asm内聯彙編,分析系統調用的全過程。

1 系統調用的概念

下圖是一個典型的系統調用圖示:

用asm内聯彙編實作系統調用1 系統調用的概念2 用asm實作系統調用的執行個體3 小結

從該函數可以看到,系統調用分成如下過程:

1. 使用者态程式調用API函數

xyz

2. 在

xyz

接口函數内部,通過中斷号

0x80

進入系統調用,此時CPU進入核心态。

3. CPU開始執行中斷處理程式,根據使用者傳入的資訊(系統調用号和相關參數),執行相應的核心态函數,并傳回結果。

這裡有兩個問題:

1. 核心态的切換是通過中斷方式進入的,而産生中斷時隻能傳入一個中斷向量(即

0x80

),而系統調用有大量的API函數,系統如何知道調用哪一個函數呢?

2. 有一些API函數帶有參數,而系統調用并沒有才有函數調用(

call

)方式,那麼參數如何傳遞到被調用函數?

答案是:在調用

int 0x80

進入系統調用前,預先把系統調用号和相關參數存入指定的寄存器中。這樣,系統調用函數隻需要通路相應的寄存器,就可以獲得所有的資訊。

事實上,在進入系統調用前,首先需要将系統調用号傳入

eax

寄存器中,并将參數依次傳入

ebx

ecx

edx

esi

edi

ebp

寄存器中。系統調用最多隻能傳入6個參數,如果參數多于6個,則需要将參數預存在記憶體中,然後将參數指針傳入寄存器。系統調用結束後,

eax

會被替換為系統調用傳回值。

2 用asm實作系統調用的執行個體

本文運作平台為實驗樓Linux核心分析的第4個實驗,運作環境為linux系統。

為了驗證系統調用的全過程,我們以exit函數為例,給出代碼如下:

#include <stdio.h>
#include <stdlib.h>
int main(){
    int id;
    scanf("%d", &id);
    switch(id){
        case :
            //用C語言的方式調用exit函數
            printf("C exit\n");
            exit();
            break;
        case :
            //用内聯彙編的方式調用exit函數
            printf("asm exit\n");
            asm volatile(
                    "mov $0, %%ebx\n\t"
                    "mov $0x1, %%eax\n\t"
                    "int $0x80\n\t"
                    :
                    :
                    );
            break;
        default:
            printf("others\n");
            break;
    }
    printf("before return\n");
    return ;
}
           

該函數中,首先輸入參數id。如果id為0,則調用C代碼的exit函數。如果id為1,則調用彙編代碼的exit函數。如果id為其他值,則順序執行至main函數結尾。

事實上,上文的代碼采用C代碼和内聯彙編實作了等價的功能,即

exit(0)

功能。可以分析一下内聯彙編的工作方式:

1.

mov $0, %ebx

:exit函數的第1個參數(也是唯一一個參數)為0,按照寄存器順序,應該放在

ebx

中。

2.

mov $0x1, %eax

:exit函數的系統調用号為

0x1

,是以把系統調用号放入

eax

中。

3.

int 0x80

:産生中斷,中斷号

0x80

表示系統調用。

執行了以上3步,即為執行了exit(0)函數。程式的運作結果如下:

用asm内聯彙編實作系統調用1 系統調用的概念2 用asm實作系統調用的執行個體3 小結

可見,輸入0或1時,都沒有輸出

"before return"

,說明exit被成功調用,程式提前退出。

3 小結

系統調用既保證了作業系統的安全運作,也友善了使用者态程式使用系統資源。用内聯彙編的方式處理系統調用,可以很清晰地看出系統調用的過程,以及系統調用的參數傳遞方式。系統調用通過寄存器傳遞參數,是以在進行系統調用前,通常還需要備份相關寄存器中的資訊。不過,在内聯彙編中,這個工作會被編譯器代勞。

繼續閱讀