一步步编写操作系统 79 在c代码中内联汇编
基本內(nèi)聯(lián)匯編是最簡單的內(nèi)聯(lián)形式,其格式為:
asm [volatile] (“assembly code”)
各關(guān)鍵字之間可以用空格或制表符分隔也可以緊湊挨在一起不分隔,各部分意義如下:
關(guān)鍵字asm用于聲明內(nèi)聯(lián)匯編表達式,這是內(nèi)聯(lián)匯編固定的部分,不可少。
asm和__asm__是一樣的,是由gcc定義的宏:#define __asm__ asm。
因為gcc有個優(yōu)化選項-O,可以指定優(yōu)化級別。當用-O來編譯時,gcc按照自己的意圖優(yōu)化代碼,說不定就會把自己所寫的代碼修改了。關(guān)鍵字volatile是可選項,它告訴gcc:“不要修改我寫的匯編代碼,請原樣保留”。volatile和__volatile__是一樣的,是由gcc定義的宏:#define __volatile__ volatile。
“assembly code”是咱們所寫的匯編代碼,它必須位于圓括號中,而且必須用雙引號引起來。這是格式要求,只要滿足了這個格式asm [volatile] (“”),assembly code甚至可以為空。
下面說下assembly code的規(guī)則:
提醒一下,即使是指令分布在多個雙引號中,gcc最終也要把它們合并到一起來處理,合并之后,指令間必須要有分隔符。所以,當指令在多個雙引號中時,除最后一個雙引號外,其余雙引號中的代碼最后一定要有分隔符,這和其它編程語言中表示代碼結(jié)束的分隔符是一樣的,如:
asm(“movl $9,%eax;””pushl %eax”)正確
asm(“movl $9,%eax””pushl %eax”)錯誤
大家注意,在內(nèi)聯(lián)匯編中,咱們要注意操作數(shù)的順序啦,現(xiàn)在是和intel反著的。
給大家舉個例子,見文件inlineASM.c
1 char* str="hello,world\n";2 int count = 0;3 void main(){4 asm("pusha; \5 movl $4,%eax; \6 movl $1,%ebx; \7 movl str,%ecx; \8 movl $12,%edx; \9 int $0x80; \ 10 mov %eax,count; \ 11 popa \ 12 "); 13 }代碼inlineASM.c是演示用匯編代碼直接調(diào)用“系統(tǒng)調(diào)用”write來打印字符患,該系統(tǒng)調(diào)用執(zhí)行后會返回打印的字符數(shù)。
第1~2行定義了兩個全局變量,待打印的字符串是str,count是用來存儲返回值
第4~12行是內(nèi)聯(lián)匯編,這是咱們之前說過的c語言中跨過運行庫直接調(diào)用系統(tǒng)調(diào)用的實例。這完全是AT&T風格的匯編語句:寄存器前面加前綴%,立即數(shù)前面加前綴$,操作數(shù)由左到右的順序。似乎看上去很簡單。
第4行將8個通用寄存器壓棧,AT&T中的匯編指令是pusha(intel中的是pushad)。
第5行是傳入第4號系統(tǒng)調(diào)用,這就是write的調(diào)用號。
第6~8行是為write系統(tǒng)調(diào)用傳入?yún)?shù),前面說系統(tǒng)調(diào)用的時候有講過參數(shù)傳遞所用到的寄存器,不再贅述。
第9行用int 0x80執(zhí)行系統(tǒng)調(diào)用,在AT&T中立即數(shù)的地位比較低,要加$前綴才表示數(shù)字為立即數(shù)(常數(shù))。
第10行是獲取write的返回值,返回值都是存儲在eax寄存器中,所以將其復制到變量count中。
好啦,編譯運行看結(jié)果,如圖
?
大家注意到?jīng)]有,inlineASM.c中的變量count和str是定義為全局變量。對的,在基本內(nèi)聯(lián)匯編中,若要引用c變量,只能將它定義為全局變量。如果定義為局部變量,鏈接時會找不到這兩個符號,這就是基本內(nèi)聯(lián)匯編的局限性,簡單的東西往往功能不夠強大,所以咱們還得學下擴展內(nèi)聯(lián)匯編形式,下一節(jié)走起。
總結(jié)
以上是生活随笔為你收集整理的一步步编写操作系统 79 在c代码中内联汇编的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 等等党胜利!AMD Zen 4架构的新一
- 下一篇: TUN/TAP设备浅析(一) -- 原理