GCC內聯彙編(INLINE ASSEMBLY) 轉
GCC內聯彙編(INLINE ASSEMBLY) 什麼是內聯彙編(Inline assembly)?
1、這是GCC對C語言的擴張,就是在C程式碼裡面去寫彙編程式碼
2、可以直接在C的語句中插入彙編指令
有何用處?
1、C語言不足以完成所有CPU的指令, 特別是有一些特權指令,比如載入gdt表(Global Descriptor Table 全域性描述符表),從而使用匯編程式碼來完成
2、用匯編在C語言中手動優化,特別是在作業系統當中,使用匯編對作業系統的掌控更為精準,更加準確。
如何工作?
1、用給定的模板和約束來生成彙編指令
2、才C函式內形成彙編程式碼
下面一個小例子,簡單看一下彙編程式碼和內聯彙編的不同:
GCC內聯彙編-Example 1
彙編程式碼 Assembly(*.S):
movl $0xffff, %eax //把0xffff給eax
內聯彙編 Inline assembly(*.c):
asm(“movl $0xffff, %%eax\n”) //1、加了一個內聯彙編關鍵字asm,把彙編程式碼括起來然後用引號表示一個字串 2、暫存器前變為%%
GCC內聯彙編-語法 asm(“assmbler template” //assmbler template就是example 1 的那個字串的內容(彙編語句)
:output operands (optional) //可選的輸出運算元(輸出暫存器)
:input operands (optional) //可選的輸入運算元(輸入暫存器)
:clobbers (optional) //會被修改的暫存器
);
GCC內聯彙編-Example2 Inline assembly(*.c)
uint32_t cr0; //一個叫cr0的變數
asm volatile(“movl %%cr0, %0\n” :"=r"(cr0)); //把cr0裡面的內容讀到%0這個暫存器當中, =r這個暫存器的內容會賦給cr0這個變數(輸出操作)
cr0 |= 0x80000000; //把某一個位設成1
asm volatile(“movl %0, %%cr0\n” ::“r”(cr0)); //再把cr0變數裡的內容寫回到cr0暫存器當中。把cr0給一個暫存器,然後這個暫存器再把他裡面的內容賦給cr0暫存器(輸入操作)
一些關鍵字的含義
volatile:No reordering; No elimination. 不需要進一步的優化,不需要進一步的調整順序
%0 :The first constraint following. 第一個用到的暫存器
r :A constraint; GCC is free to use any register. 任意一個暫存器
上面的內聯彙編所對應的彙編程式碼如下
Generated assembly code(*.s):
movl %cr0, %ebx //cr0 --> ebx
movl %ebx, 12(%esp) //ebx賦給一個區域性變數12(%esp)
orl $-2147483648, 12(%esp) //或操作
movl 12(%esp), %eax //再給eax
movl %eax, %cr0 //再把eax暫存器裡面的內容賦給cr0
GCC內聯彙編-Example3 Inline assembly(*.c)
long _res, arg1 = 2, arg2 = 22, arg3 = 222, arg4 = 233;
_asm_volatile(“int $0x80”
:"=a"(_res)
:“0”(11), “b”(arg1), “c”(arg2), “d”(arg3), “S”(arg4)); //把arg1給ebx, arg2給ecx,arg3給edx, arg4給esi
在內聯彙編當中
a = %eax, b = %ebx, c = %ecx, d = %edx, S = %esi, D = %edi, 0 = same as the first 第一個出現的暫存器
Generated assembly code(*.s):
mov $11, %eax
movl-28(%ebp), %ebx
movl-24(%ebp), %ecx
movl-20(%ebp), %edx
movl-16(%ebp), %esi
int $0x80
movl %edi, -12(%ebp)
如果想要了解GCC內聯彙編更多的知識,請訪問