i386 和 x86-64 架構下 UNIX & Linux 系統呼叫的呼叫約定是什麼?
系統呼叫是應用程式和 Linux 核心之間的基本介面。當一個 Unix/Linux 程式進行檔案 I/O、網路資料傳輸或呼叫直接或間接與底層指令互動的某些程序時,就會涉及系統呼叫。進行這些呼叫通常涉及使用名為 **glibc** 的庫,其中包含這些函式。
示例
以下是一些常用系統呼叫及其用途的列表。
序號 | 系統呼叫 | 用途 |
---|---|---|
1 | chmod | 更改檔案許可權 |
2 | chdir | 更改工作目錄 |
3 | fork | 建立子程序 |
4 | unlink | 刪除名稱,並可能刪除它所引用的檔案 |
系統程式設計師編寫的程式不會直接進行系統呼叫,而是隻會指定要使用的系統呼叫。這涉及使用取決於核心所在系統硬體架構的呼叫約定。因此,不同的架構具有不同的呼叫約定。
呼叫約定是在實現級別上設計子程式如何從呼叫者接收引數以及如何返回結果。各種實現的差異包括引數、返回值、返回地址和作用域連結的位置(暫存器、堆疊或記憶體等),以及在呼叫函式之前進行準備和之後恢復環境的任務如何在呼叫者和被呼叫者之間分配。
呼叫約定差異
以下是描述呼叫約定在不同架構之間如何變化的一些場景列表。
- 被呼叫函式必須為呼叫者保留哪些暫存器。
- 呼叫函式之前和之後進行設定和清理的任務如何在呼叫者和被呼叫者之間分配。
- 返回值如何從被呼叫者傳遞迴呼叫者——在堆疊上、在暫存器中或在堆中。
- 引數、返回值和返回地址放置的位置。
- 傳遞形式引數的實際引數的順序。
比較 x86-32 和 x86-64 位
單個 CPU 架構總是有多個可能的呼叫約定,但業界已就不同生產商的架構達成了一些通用方法。32 位架構有 32 個暫存器,而 x64 將 x86 的 8 個通用暫存器擴充套件為 64 位。因此,呼叫約定的實現存在差異。以下是這兩種架構之間主要呼叫約定的比較。
x-86 32位 | x-86 64位 |
---|---|
用於系統呼叫的暫存器為:%ebx、%ecx、%edx、%esi、%edi、%ebp | 用於系統呼叫的暫存器為:%rdi、%rsi、%rdx、%r10、%r8 和 %r9 |
使用 PUSH 機制在堆疊上傳遞引數。如果引數超過六個,%ebx 必須包含儲存引數列表的記憶體位置。 | 系統呼叫最多隻能有六個引數。如果超過 6 個 INTEGER 引數,則第 7 個 INTEGER 引數及以後的引數將透過堆疊傳遞。 |
返回值儲存在 %eax 暫存器中。 | 返回值儲存在 %rax 暫存器中。 |
在 x86-32 中,引數透過堆疊傳遞。最後一個引數首先壓入堆疊,直到所有引數都完成,然後執行呼叫指令。 | 首先將引數劃分為幾類。每個引數的類別決定它傳遞給被呼叫函式的方式。 |
32 位 int ABI(應用程式二進位制介面)可在 64 位程式碼中使用。 | 64 位 ABI 呼叫不能在 32 位系統中使用。 |
廣告