談談 Qt 程式安裝包的大小,以及簡要打包指南
阿新 • • 發佈:2022-12-05
基本內聯彙編
基本內聯彙編的語法很簡單,實現的功能也很簡單,就是直接將彙編語句插入到編譯後的C程式碼中。基本形式如下。
asm("assembly code");
例如。
asm("nop"); asm("cli");
可以通過加入換行\n\t
寫多行內聯彙編。
asm( "pushl %eax\n\t"
"movl $0,%eax\n\t"
"popl %eax"
);
但基本內聯彙編有很大的問題,那就是編譯器其實是不知道你寫的內聯彙編程式碼語義是什麼,如果你在基本內聯彙編裡面對暫存器,或者記憶體做了什麼修改它是不知道的,還是照常編譯C程式碼,這就會出現衝突。
並且還有一個缺點就是沒法和C程式碼中的變數進行互動,只能自己玩自己的,這樣你就是想改變C程式碼中的一個變數也做不到。
擴充套件內聯彙編
擴充套件內聯彙編使用更復雜的語法,來指示編譯器自己將對哪些暫存器或者記憶體做修改,並且還可以使用C程式碼中的變數。其基本語法如下。
asm ( assembler template : output operands /* optional */ : input operands /* optional */ : clobbered list /* optional */ );
-
assembler template
彙編模板:就是要執行的彙編程式碼,並且其中可以使用佔位符來指代後面的輸出和輸入變數,佔位符從%0
開始,依次是%1
,%2
等等。 -
output/input operands
輸出和輸入運算元,則可以將C程式碼中的變數和暫存器或者記憶體繫結起來,讓編譯器知道彙編模板中的程式碼會影響哪些暫存器和記憶體。 -
clobbered list
改動列表,可以用來告訴編譯器在輸出和輸入運算元中沒用提及的,但是發生了改動的暫存器和記憶體。
例子如下。
int a=10, b; asm ("movl %1, %%eax; movl %%eax, %0;" :"=r"(b) /* output */ :"r"(a) /* input */ :"%eax" /* clobbered register */ );
這裡輸入輸出運算元和r
繫結起來,這裡r
的意思就是讓編譯器自己決定用哪個暫存器來快取,對輸出運算元還加了=
表示賦值的意思。而在彙編模板中的%0
和%1
佔位符,用來指代輸出輸入運算元,從左到右從0開始編號。
最後注意到clobbered list
還貼心地寫上了%eax
,那是因為在輸出輸入運算元中沒有提及該暫存器,但實際的彙編程式碼中又會改動這個暫存器,所以需要手動告訴編譯器自己的程式碼也會影響到%eax
暫存器。
常用限制符
限制符就是在輸出輸入運算元中約束C變數與暫存器或者記憶體的關係的符號。
字母 | 含義 |
---|---|
r | 任何通用暫存器 |
q | 暫存器eax, ebx, ecx或edx |
a, b, c, d | 對應的暫存器eax,ebx,ecx,edx |
S | 暫存器esi |
D | 暫存器edi |
A | 把eax和edx合成一個64 位的暫存器 |
m | 記憶體變數 |
o | 記憶體變數,但是其定址方式是偏移量型別 |
V | 記憶體變數,但定址方式不是偏移量型別 |
I | 0-31之間的立即數(用於32位移位指令) |
J | 0-63之間的立即數(用於64位移位指令) |
N | 0-255之間的立即數(用於out指令) |
i | 立即數 |
n | 立即數 |
f | 浮點暫存器 |
t | 第一個浮點暫存器 |
u | 第二個浮點暫存器 |
G | 標準的80387浮點常數 |
常用clobber list
關鍵字 | 含義 |
---|---|
memory | 指令以一種不可預知的方式修改了記憶體,用memory告知編譯器 |
cc | 標誌暫存器發生了改動 |