名詞概念
就是在C語言中可以插入彙編語言,,,
彙編程式簡述
Linux 中使用的基本彙編程式語法。GCC(用於 Linux 的 GNU C
編譯器)使用 AT&T 彙編語法。下面列出了這種語法的一些基本規則。
暫存器命名
暫存器名稱有 % 前綴。即,如果必須使用 eax,它應該用作 %eax。
運算元的順序
在所有指令中,先是源運算元,然後才是目的運算元。這與將源運算元放在目的運算元之後的 Intel 語法不同。
mov %eax, %ebx, transfers the contents of eax to ebx.
|
運算元大小
根據運算元是位元組 (byte)、字 (word) 還是長型 (long),指令的後綴可以是 b、w 或 l。這並不是強制性的;GCC 會嘗試通過讀取運算元來提供相應的後綴。但手工指定後綴可以改善代碼的可讀性,並可以消除編譯器猜測不正確的可能性。
movb %al, %bl -- Byte move movw %ax, %bx -- Word move movl %eax, %ebx -- Longword move
|
立即運算元
通過使用 $ 指定直接運算元。
movl $0xffff, %eax -- will move the value of 0xffff into eax register.
|
間接記憶體引用
任何對記憶體的間接引用都是通過使用 ( ) 來完成的。
movb (%esi), %al -- will transfer the byte in the memory pointed by esi into alregister
|
內聯彙編
GCC 為內聯彙編提供特殊結構,它具有以下格式:
GCG 的 "asm" 結構
asm ( assembler template
: output operands (optional)
: input operands (optional)
: list of clobbered registers
(optional)
);
內聯彙編的重要性體現在它能夠靈活操作,而且可以使其輸出通過 C 變數顯示出來。因為它具有這種能力,所以 "asm" 可以用作
彙編指令和包含它的 C 程式之間的接口。
一個非常基本但很重要的區別在於
簡單內聯彙編只包括指令,而
擴展內聯彙編包括
運算元。要說明這一點,考慮以下示例:
內聯彙編的基本要素
{ int a=10, b; asm ("movl %1, %%eax; movl %%eax, %0;" :"=r"(b) /* output */ :"r"(a) /* input */ :"%eax"); /* clobbered register */}
在上例中,我們使用彙編指令使 "b" 的值等於 "a"。請注意以下幾點:
"b" 是輸出
運算元,由 %0 引用,"a" 是輸入運算元,由 %1 引用。 "r" 是運算元的約束,它指定將變數 "a" 和 "b" 存儲在
暫存器中。請注意,輸出
運算元約束應該帶有一個約束修飾符 "=",指定它是輸出運算元。 要在 "asm" 內使用
暫存器 %eax,%eax 的前面應該再加一個 %,換句話說就是 %%eax,因為 "asm" 使用 %0、%1 等來標識
變數。任何帶有一個 % 的數都看作是輸入/輸出
運算元,而不認為是
暫存器。 第三個冒號後的修飾
暫存器 %eax 告訴將在 "asm" 中修改 GCC %eax 的值,這樣 GCC 就不使用該暫存器
存儲任何其它的值。 movl %1, %%eax 將 "a" 的值移到 %eax 中, movl %%eax, %0 將 %eax 的內容移到 "b" 中。 因為 "b" 被指定成輸出
運算元,因此當 "asm" 的執行完成後,它將反映出更新的值。換句話說,對 "asm" 內 "b" 所做的更改將在 "asm" 外反映出來。