GCC內聯彙編


一.基本內聯彙編的格式是:
__asm__ __volatile__("Instruction List");

1. __asm__
__asm__是GCC 關鍵字asm 的宏定義:
#define __asm__ asm
__asm__或asm 用來聲明一個內聯彙編表達式,所以任何一個內聯彙編表達式都是以它開頭的,是必不可少的。

2. Instruction List
Instruction List 是彙編指令序列。它可以是空的,比如:__asm__ __volatile__(""); 或
__asm__ ("");都是完全合法的內聯彙編表達式,只不過這兩條語句沒有什麼意義。但並非所有Instruction List 爲空的內聯彙編表達式都是沒有意義的,比如:__asm__ ("":::"memory");
就非常有意義,它向GCC 聲明:“內存作了改動”,GCC 在編譯的時候,會將此因素考慮進去。
當在"Instruction List"中有多條指令的時候,可以在一對引號中列出全部指令,也可以將一條
或幾條指令放在一對引號中,所有指令放在多對引號中。如果是前者,可以將每一條指令放在一行,如果要將多條指令放在一行,則必須用分號(;)或換行符(/n)將它們分開.
綜上述:(1)每條指令都必須被雙引號括起來 (2)兩條指令必須用換行或分號分開。
例如:
__asm__("movl %eax, %ebx; sti/n/t"
"popl %edi; subl %ecx, %ebx");

3. __volatile__
__volatile__是GCC 關鍵字volatile 的宏定義
#define __volatile__ volatile
__volatile__或volatile 是可選的。如果用了它,則是向GCC 聲明不允許對該內聯彙編優化,否則當
使用了優化選項(-O)進行編譯時,GCC 將會根據自己的判斷決定是否將這個內聯彙編表達式中的指令優化掉。

在基本內聯彙編裏可以使用全局變量

二.擴展的內聯彙編格式爲
__asm__ __volatile__("Instruction List"
: Output
: Input
: Clobber/Modify);

這4 個部分都不是必須的,任何一個部分都可以爲空,其規則爲:
(1)如果Clobber/Modify 爲空,則其前面的冒號(:)必須省略。比如
__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) : )就是非法的寫法;
而__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) )則是正確的。
(2)如果Instruction List 爲空,則Input,Output,Clobber/Modify 可以不爲空,也可以爲空。
比如__asm__ ( " " : : : "memory" );和__asm__(" " : : );都是合法的寫法。
(3)如果Output,Input,Clobber/Modify 都爲空,Output,Input 之前的冒號(:)既可以省略,
也可以不省略。如果都省略,則此彙編退化爲一個基本內聯彙編,否則,仍然是一個擴展的內聯彙編,
此時"Instruction List"中的寄存器寫法要遵守相關規定,比如寄存器前必須使用兩個百分號(%%),而不是像基本彙編格式一樣在寄存器前只使用一個百分號(%) 。
比如__asm__( " mov %%eax,%%ebx" : : );
__asm__( " mov %%eax, %%ebx" : )和__asm__( " mov %eax, %ebx" )都是正確的寫法,
而__asm__( " mov %eax, %ebx" : : );__asm__( " mov %eax,%ebx" : );
__asm__( " mov %%eax, %%ebx" )都是錯誤的寫法。
(4) 如果Input,Clobber/Modify 爲空,但Output 不爲空,Input 前的冒號(:)既可以
省略,也可以不省略。比如__asm__( " mov %%eax, %%ebx" : "=b"(foo) : );
__asm__( " mov %%eax, %%ebx" : "=b"(foo) )都是正確的。
(5)如果後面的部分不爲空,而前面的部分爲空,則前面的冒號(:)都必須保留,否則無
法說明不爲空的部分究竟是第幾部分。比如, Clobber/Modify,Output 爲空,
而Input 不爲空,則Clobber/Modify 前的冒號必須省略(前面的規則),而Output
前的冒號必須爲保留。如果Clobber/Modify 不爲空,而Input 和Output 都爲空,
則Input 和Output 前的冒號都必須保留。比如__asm__( " mov %%eax, %%ebx" : :
"a"(foo) )和__asm__( " mov %%eax, %%ebx" : : : "ebx" )。
總之不能有歧義.

1. Output
Output 用來指定當前內聯彙編語句的輸出
2. Input
Input 域的內容用來指定當前內聯彙編語句的輸入
Output和Input中,格式爲形如“constraint”(variable)的列表(逗號分隔)
3. Clobber/Modify
Clobber/Modify 聲明當前內聯彙編在Instruction List中對某些寄存器或內存進行修改。不能有Input或Output中限制的寄存器

===================================================================================
Constraint Description
a Use the %eax, %ax, or %al registers.
b Use the %ebx, %bx, or %bl registers.
c Use the %ecx, %cx, or %cl registers.
d Use the %edx, %dx, or $dl registers.
S Use the %esi or %si registers.
D Use the %edi or %di registers.
r Use any available general-purpose register.
q Use either the %eax, %ebx, %ecx, or %edx register.
A Use the %eax and the %edx registers for a 64-bit value.
f Use a floating-point register.
t Use the first (top) floating-point register.
u Use the second floating-point register.
m Use the variable’s memory location.
o Use an offset memory location.
V Use only a direct memory location.
i Use an immediate integer value.
n Use an immediate integer value with a known value.
g Use any register or memory location available.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章