內嵌彙編語法如下:
__asm__(彙編語句模板: 輸出部分: 輸入部分: 破壞描述部分)
共四個部分:彙編語句模板,輸出部分,輸入部分,破壞描述部分,各部分使用「:」格開,彙編語句模板必不可少,其他三部分可選,如果使用了後面的部分,而前面部分為空,也需要用「:」格開,相應部分內容為空。例如:
__asm__ __volatile__("cli": : :"memory")
1、彙編語句模板
彙編語句模板由彙編語句序列組成,語句之間使用「;」、「/n」或「/n/t」分開。指令中的運算元可以使用佔位符引用c語言變數,運算元佔位符最多10個,名稱如下:%0,%1,…,%9。指令中使用佔位符表示的運算元,總被視為
long型(4個位元組),但對其施加的操作根據指令可以是字或者位元組,當把運算元當作字或者位元組使用時,預設為低字或者低位元組。對位元組操作可以顯式的指明是低位元組還是次位元組。
方法是在%和序號之間插入乙個字母,「b」代表低位元組,「h」代表高位元組,例如:%h1。
2、輸出部分
輸出部分描述輸出運算元,不同的運算元描述符之間用逗號格開,每個運算元描述符由限定字串和c 語言變數組成。每個輸出運算元的限定字串必須包含「=」表示他是乙個輸出運算元。
例: __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x) )
描述符字串表示對該變數的限制條件,這樣gcc 就可以根據這些條件決定如何分配暫存器,如何產生必要的**處理指令運算元與c表示式或c變數之間的聯絡。
3、輸入部分
輸入部分描述輸入運算元,不同的運算元描述符之間使用逗號格開,每個運算元描述符由限定字串和c語言表示式或者c語言變數組成。
例1 :
__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
例二(bitops.h):
static __inline__ void __set_bit(int nr, volatile void * addr)
後例功能是將(*addr)的第nr位設為1。第乙個佔位符%0與c 語言變數addr對應,第二個佔位符%1與c語言變數nr對應。因此上面的彙編語句**與下面的偽**等價:btsl nr, addr,該指令的兩個運算元不能全是記憶體變數,因此將nr的限定字串指定為「ir」,將nr 與立即數或者暫存器相關聯,這樣兩個運算元中只有addr為記憶體變數。
4、限制字元
4.1、限制字元列表
限制字元有很多種,有些是與特定體系結構相關,此處僅列出常用的限定字元和i386中可能用到的一些常用的限定符。它們的作用是指示編譯器如何處理其後的c語言變數與指令運算元之間的關係。
分類 限定符 描述
通用暫存器 「a」 將輸入變數放入eax
這裡有乙個問題:假設eax已經被使用,那怎麼辦?
其實很簡單:因為gcc 知道eax 已經被使用,它在這段彙編**
的起始處插入一條語句pushl %eax,將eax 內容儲存到堆疊,然
後在這段**結束處再增加一條語句popl %eax,恢復eax的內容
「b」 將輸入變數放入ebx
「c」 將輸入變數放入ecx
「d」 將輸入變數放入edx
「s」 將輸入變數放入esi
「d」 將輸入變數放入edi
「q」 將輸入變數放入eax,ebx,ecx,edx中的乙個
「r」 將輸入變數放入通用暫存器,也就是eax,ebx,ecx,
edx,esi,edi中的乙個
「a」 把eax和edx合成乙個64 位的暫存器(use long longs)
記憶體 「m」 記憶體變數
「o」 運算元為記憶體變數,但是其定址方式是偏移量型別,
也即是基址定址,或者是基址加變址定址
「v」 運算元為記憶體變數,但定址方式不是偏移量型別
「 」 運算元為記憶體變數,但定址方式為自動增量
「p」 運算元是乙個合法的記憶體位址(指標)
暫存器或記憶體 「g」 將輸入變數放入eax,ebx,ecx,edx中的乙個
或者作為記憶體變數
「x」 運算元可以是任何型別
立即數
「i」 0-31之間的立即數(用於32位移位指令)
「j」 0-63之間的立即數(用於64位移位指令)
「n」 0-255之間的立即數(用於out指令)
「i」 立即數
「n」 立即數,有些系統不支援除字以外的立即數,
這些系統應該使用「n」而不是「i」
匹配 「 0 」, 表示用它限制的運算元與某個指定的運算元匹配,
「1」 ... 也即該運算元就是指定的那個運算元,例如「0」
「9」 去描述「%1」運算元,那麼「%1」引用的其實就
是「%0」運算元,注意作為限定符字母的0-9 與
指令中的「%0」-「%9」的區別,前者描述運算元,
後者代表運算元。
& 該輸出運算元不能使用過和輸入運算元相同的暫存器
運算元型別 「=」 運算元在指令中是只寫的(輸出運算元)
「+」 運算元在指令中是讀寫型別的(輸入輸出運算元)
浮點數 「f」 浮點暫存器
「t」 第乙個浮點暫存器
「u」 第二個浮點暫存器
「g」 標準的80387浮點常數
% 該運算元可以和下乙個運算元交換位置
例如addl的兩個運算元可以交換順序
(當然兩個運算元都不能是立即數)
# 部分注釋,從該字元到其後的逗號之間所有字母被忽略
* 表示如果選用暫存器,則其後的字母被忽略
5、破壞描述部分
破壞描述符用於通知編譯器我們使用了哪些暫存器或記憶體,由逗號格開的字串組成,每個字串描述一種情況,一般是暫存器名;除暫存器外還有「memory」。例如:「%eax」,「%ebx」,「memory」等。
GCC內嵌彙編
gcc內嵌彙編 限制字元 限制字元有很多種,有些是與特定體系結構相關,此處僅列出常用的限定字元和i386中可能用到的一些常用的限定符。它們的作用是指示編譯器如何處理其後的c語言變數與指令運算元之間的關係,例如是將變數放在暫存器中還是放在記憶體中等,下表列出了常用的限定字母。b 將輸入變數放入ebx ...
GCC內嵌彙編學習筆記
本文主要對gcc內嵌彙編一文的簡要總結,試著用自己的話把gcc彙編的關鍵點描述出來,以驗證自己是否真正理解。本文將以 linux核心完全注釋 v3 中的乙個例子進行描述,這個例子我看的時候是非常的懵逼,直到看了gcc內嵌彙編一文。gcc內嵌彙編的基本結構 asm 彙編語句列表 輸出暫存器 輸入暫存器...
GCC使用的內嵌彙編語法格式小教程
本文對內嵌彙編語法,從基本語法 內嵌彙編的格式介紹 和擴充套件的內嵌彙編格式進行了詳細說明,需要說明的是gcc採用的是at t的彙編格式 一 基本語法 語法上主要有以下幾個不同.暫存器命名原則 at t eax intel eax 源 目的運算元順序 at t movl eax,ebx intel ...