1. 程式人生 > 其它 >談談 Qt 程式安裝包的大小,以及簡要打包指南

談談 Qt 程式安裝包的大小,以及簡要打包指南

基本內聯彙編

基本內聯彙編的語法很簡單,實現的功能也很簡單,就是直接將彙編語句插入到編譯後的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 標誌暫存器發生了改動

參考資料