2011-08-01 62 views
5

我需要一些參考,但很好,可能有一些很好的例子。我需要它,因爲我開始使用NASM彙編程序在程序集中編寫代碼。我有這樣的參考:系統調用的很好的參考

http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html

這是相當不錯的和有用的,但它有很大的侷限性,因爲它並不能解釋其他寄存器的字段。例如,如果我使用寫入系統調用,我知道我應該把1放在EAX寄存器中,而ECX可能是一個指向字符串的指針,但EBX和EDX呢?我希望可以這樣解釋,EBX確定輸入(0表示stdin,1表示其他東西等),EDX是要輸入的字符串的長度等等。我希望你明白我想要什麼,我找不到任何這樣的材料,所以這就是我寫在這裏的原因。 在此先感謝。

回答

0

如果您下載該網頁(如第二段中所述)並下載內核源代碼,則可以單擊「源代碼」列中的鏈接,然後直接轉到實現系統調用的源文件。您可以閱讀他們的C簽名以查看每個參數的用途。

如果您只是在尋找快速參考,那麼每個系統調用都有一個C庫接口,其名稱相同,即減去sys_。因此,舉例來說,你可以檢查出man 2 lseek以獲取有關參數信息sys_lseek

off_t lseek(int fd, off_t offset, int whence); 

這裏,你可以看到,參數從你的HTML表格匹配的:

%ebx   %ecx %edx 
unsigned int off_t unsigned int 
+0

當然,即使你在谷歌或任何源代碼搜索工具中搜索它的每一個實現,你可以找到直接的例子如何使用它們 - 我做了什麼。我的文章的要點是跳過搜索和分析一些不錯的小抄。謝謝。 –

11

Linux中的標準編程語言是C.因此,系統調用的最佳描述將顯示它們爲要調用的C函數。將它們的描述作爲C函數,並且知道如何將它們映射到實際的彙編系統調用中,您將能夠輕鬆使用任何系統調用。

首先,您需要所有系統調用的參考,因爲它們看起來像一個C程序員。我所知道的最好的是Linux man-pages project,特別是system calls部分。

讓我們以write系統調用爲例,因爲它是你問題中的一個。正如你所看到的,第一個參數是一個有符號整數,它通常是由系統調用返回的文件描述符。這些文件描述符也可能已經從父進程繼承,通常發生在前三個文件描述符(0 = stdin,1 = stdout,2 = stderr)。第二個參數是指向緩衝區的指針,第三個參數是緩衝區的大小(作爲無符號整數)。最後,函數返回一個有符號的整數,它是寫入的字節數,或者是一個錯誤的負數。

現在,如何將其映射到實際的系統調用?有許多方法可以在32位x86上執行系統調用(這可能是您使用的,基於您的註冊名稱);請注意,它在64位x86上完全不同(請確保您正在以32位模式進行組裝,並鏈接一個32位可執行文件;請參閱this question,以獲取有關如何防止事情發生錯誤的示例)。 32位x86中最老,最簡單和最慢的方法是int $0x80方法。

對於int $0x80方法,你把系統調用號在%eax,並在參數%ebx%ecx%edx%esi%edi%ebp,按照這個順序。然後您撥打int $0x80,系統調用返回值爲%eax。注意這個返回值是不同於這個參考文獻說的;該參考顯示C庫將如何返回它,但系統調用返回-errno錯誤(例如-EINVAL)。在這種情況下,C庫將把它移動到errno並返回-1。有關更多詳細信息,請參見syscalls(2)intro(2)

所以,在write例如,可以把在%eaxwrite系統調用號,在%ebx第一個參數(文件描述符),在%ecx第二個參數(字符串指針),第三個參數(字符串的長度)在%edx。系統調用將返回%eax或者寫入的字節數,或者返回錯誤編號(如果返回值在-1和-4095之間,則爲錯誤編號)。

最後,你如何找到系統呼叫號碼?他們可以在/usr/include/linux/unistd.h找到。在我的系統上,這隻包括/usr/include/asm/unistd.h,最後包括/usr/include/asm/unistd_32.h,所以數字在那裏(對於write,你可以看到__NR_write4)。錯誤號碼來自/usr/include/linux/errno.h(在我的系統中,在追逐包含鏈後,我在/usr/include/asm-generic/errno-base.h找到第一個,其餘的爲/usr/include/asm-generic/errno.h)。對於使用其他常量或結構的系統調用,它們的文檔會告訴您應該查看哪些頭以找到相應的定義。


現在,正如我所說,int $0x80是最古老和最慢的方法。較新的處理器具有更快的特殊系統調用指令。爲了使用它們,內核提供了一個虛擬的動態共享對象(vDSO;它就像一個共享庫,但只在內存中),並且可以調用一個函數來使用可用於硬件的最佳方法進行系統調用。它還提供特殊功能來獲取當前時間,而無需執行系統調用等幾件事情。當然,如果你不使用動態鏈接器,使用起來會有點困難。

還有另一種較舊的方法,vsyscall,它類似於vDSO,但在固定地址使用單個頁面。如果您使用的是最新的內核,可能會在最近的內核上引導時禁用此方法,並且可能會在將來刪除此方法,但會導致系統日誌中出現警告。不要使用它。

+0

這是我見過的最好的答案之一。 –