一起學(xué)習(xí)在linux下使用匯編語言(2)
2024-07-21 02:37:19
供稿:網(wǎng)友
作者:luster
摘要:GNU C/C++編譯器(GCC)是一個32-bit的編譯器,是GNU計劃的核心,能非常好的支持x86體系結(jié)構(gòu),它支持在C程序里面嵌入?yún)R編代碼,這樣看來,寄存器可以自己指定也可以留給gcc來分配。 GCC可以在多個平臺下使用,除了linux,還有*BSD, VSTa, OS/2, *DOS, Win*等等。
3. 匯編器
gcc內(nèi)嵌編譯器
GNU C/C++編譯器(GCC)是一個32-bit的編譯器,是GNU計劃的核心,能非常好的支持x86體系結(jié)構(gòu),它支持在C程序里面嵌入?yún)R編代碼,這樣看來,寄存器可以自己指定也可以留給gcc來分配。GCC可以在多個平臺下使用,除了linux,還有*BSD, VSTa, OS/2, *DOS, Win*等等。
可以在GNU FTP站點下載GCC。鏈接是:
ftp://PRep.ai.mit.edu/pub/gnu/gcc/
現(xiàn)在GCC已經(jīng)分裂成兩個分支(GCC 2.8和EGCS),但是它們又重新合并了起來,GCC的主頁位于:http://gcc.gnu.org.
因為內(nèi)核頭文件中定義的一些匯編例程函數(shù)都是extern inline函數(shù),所以GCC必須要加-O(或者-O2,-O3等)編譯標(biāo)志,這樣才能使得這些函數(shù)可以使用。否則,假如不加-O標(biāo)志,代碼也可以被編譯,但是可能link會不正確。
嵌入?yún)R編語言可以通過“-fno-asm”來被禁止。不過通常來說,比較好的編譯標(biāo)志是如下的,這對于大多數(shù)的x86平臺都是很不錯的選擇:
gcc -O2 -fomit-frame-pointer -W -Wall
-O2在大部分情況下都是很好的代碼優(yōu)化級別。事實上,使用優(yōu)化后會帶來更多的編譯時間,也會產(chǎn)生大一些地代碼,而在速度上僅僅有一點點提高。
-fomit-frame-pointer答應(yīng)產(chǎn)生的代碼中跳過一些錯誤的frame pointer maintenance,這樣可以使得代碼小一些而且快一些,而且會釋放一些寄存器來獲得更進一步的優(yōu)化。
-W –Wall使得我們可以獲得很多有用的warning,這對于我們減少一些愚蠢的編碼錯誤是非常有用的。
我們還可以加一些編譯參數(shù)來指明目標(biāo)CPU的類型,這樣就答應(yīng)GCC來產(chǎn)生一些針對特定CPU的優(yōu)化代碼。在編譯內(nèi)核中使用指明CPU類型的參數(shù)是非常有用的。具體GCC支持什么類型CPU優(yōu)化,我們可以參考所使用的GCC的文檔。
GCC對宏的支持
GCC答應(yīng)而且要求你指明你的嵌入?yún)R編代碼使用的寄存器,這樣編譯器的優(yōu)化器才能知道如何優(yōu)化。因此,嵌入?yún)R編代碼通常是一些patterns,而不是真正的代碼(exact code)。因此,通常我們把匯編代碼放到CPP的宏定義里面,或者定義成inline函數(shù),這樣就可以方便的就像使用C函數(shù)或宏一樣使用這些代碼。Inline函數(shù)和宏非常相似,不過inline函數(shù)比較起后者,使用起來更清楚。
GAS
GAS是GNU的匯編器,GCC實際上也依靠它。我們可以在任何能下載GCC的地方找到這個實用工具,它通常位于一個名叫binutils的包里面。下面的URL給出了最新的版本:
ftp://ftp.varesearch.com/pub/support/hjl/binutils/.
GAS是一個支持32-bit的unix環(huán)境下的匯編編譯器,它使用標(biāo)準(zhǔn)的AT&T語法,它使用標(biāo)準(zhǔn)的m68k編譯器的語法,這是UNIX world的標(biāo)準(zhǔn)。這個語法和Intel的語法不一樣,假如你適應(yīng)了這種語法,那么你就會發(fā)現(xiàn)它也是很好用的。下面是一些GAS語法的主要特點:
· 所有的寄存器的名字都是以“%”最為前綴,所以可能的一些寄存器是%eax,%dl等等,而不是簡單的eax,dl等。這樣的話可以使得C語言中方便的嵌入一些匯編代碼而不會有變量名字方面沖突的擔(dān)心。
· 操作數(shù)的順序也是相反的。例如要把edx寄存器的內(nèi)容拷貝到eax寄存器里面的話,GAS的語法是:mov %edx,%eax;而Intel平臺下的匯編語句是:mov eax,edx。
· 操作數(shù)的尺寸作為一個后綴加在操作名的后面。B表示(8-bit)byte,w表示(16-bit) Word,l表示(32-bit) long。例如,上面例子中正確的語法應(yīng)該是:movl %edx,%eax。不過,GAS并不需要嚴(yán)格的AT&T語法,所以這個后綴可可以省略的,這時候編譯器就自己根據(jù)操作數(shù)判定或者置為缺省的位寬32-bit。
· 立即數(shù)需要一個“$”前綴符號,例如:addl $5,%eax。
· 假如沒有操作數(shù)前綴,則表示它是內(nèi)存地址,例如:movl $foo,%eax,把變量foo的地址送到了%eax寄存器。但是“movl foo,%eax”則把foo變量的內(nèi)容送到eax寄存器中。
已經(jīng)有一些工具可以幫助你把你的使用Intel匯編語法的源程序轉(zhuǎn)換成AT&T語法,或者做相反的轉(zhuǎn)換。
不過,已經(jīng)有的好消息是Binutils 2.10開始,GAS已經(jīng)可以支持Intel語法了。
16-bit mode
Binutils (2.9.1.0.25+) 可以全面支持i386PC體系下的16-bit模式(存儲器和尋址)。
使用“.code16”和“.code32”來切換匯編模式。
還有很多的編譯器,我們可以選擇,明天再學(xué)習(xí)把。
昨天晚上美國遭到恐怖襲擊,去看電視直播去了。拜拜。今天到此。
luster@linuxaid.com.cn