GCC內嵌彙編語法

2021-06-07 13:20:51 字數 3430 閱讀 2988

內嵌彙編語法如下:

__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 ...