開門見山,組合語言和c語言混合程式設計可分為兩大類:
單獨的彙編**檔案與單獨的c語言分別編譯成目標檔案後,一起鏈結成可執性檔案
在c語言中嵌入彙編**,直接編譯生成可執行程式
今天主要介紹第二種
內聯彙編稱為inline assembly, gcc支援在c**中直接嵌入彙編**,所以稱為gcc inline assembly.
內聯彙編按格式分為兩大類,一類是最簡單的基本內聯彙編,另一類是複雜一些的擴充套件內聯彙編.(內聯彙編中所用的組合語言是at&t,並不是咋們熟悉的intel語法,gcc只支援它, at&t是組合語言的一種語法風格,格式.在某一處理器平台上,無論彙編**是什麼語法,其編譯出來的**是一樣的,所以不要誤以為at&t是一種新的機器語言.它僅僅是表達方式不同,意思是一樣的)
基本內聯彙編
格式:asm[volatile] ("assembly code")
gcc有個優化選項 -o,可以指定優化級別.當用-o來編譯時,gcc按照自己的意圖優化**,說不定就會把自己所寫的**修改了. 關鍵字volatile是可選項,它告訴gcc:「不要修改我的彙編**,請原樣保留」
"assembly code"是咱們所寫的彙編**,他必須位於圓括號中,而且必須用雙引號引起來.這是格式要求,可以為空.規則:
(1) 指令必須用雙引號引起來,無論雙引號中是一條指令或多條指令
(2) 一對引號不能跨行,如果跨行需要在結尾用反斜槓\
轉義
(3) 指令之間用;
, 換行符\n
或 換行符加製表符\n\t
分隔
擴充套件內聯彙編char *str = "hello world\n";
int count = 0;
void main()
gcc本身是個c編譯器, 要讓其支援組合語言,必然牽扯以下問題:
暫存器約束
a : %eax, %ax, %al
b : %ebx, %bx, %bl
c : %ecx, %cx, %cl
d : %edx, %dx, %dl
s : %esi, %si
d : %edi, %di
// 基本內聯彙編
int in_a = 1, in_b = 2, out_sum;
void main()
記憶體運算元約束(memory operand constraint, m)//擴充套件內聯彙編
void main()
當我們不想通過暫存器中轉,而是直接操作記憶體時,可以用"m"來約束。例如:
asm volatile ( 「lock; decl %0」 : 「=m」 (counter) : 「m」 (counter));
立即數約束(不太常用)
通用約束
為方便對運算元的引用,擴充套件內聯彙編提供了佔位符,它的作用是代表約束指定的運算元(暫存器, 記憶體, 立即數).
佔位符分為序號佔位符和名稱佔位符兩種序號佔位符是對output和input中的運算元,按照他們從左到右出現的次序從0開始編寫.引用它的格式是%0~9
asm("addl %%ebx, %%eax" : "=a"(out_sum) : "a"(in_a), "b"(in_b));
等價於asm("addl %2, %1" : "=a"(out_sum) : "a"(in_a), "m"(in_b));
可以通過gcc -s -o filename.s filename.c
cat filename.s
來檢視暫存器的使用情況,你就會明白擴充套件內聯彙編的具體優異之處
Linux C語言內聯彙編使用
最近要改個c語言演算法的關鍵部分用組合語言實現,linux裡嵌入彙編基本使用at t彙編,比如linux系統的啟動部分用的就是at t彙編 以前學過at t彙編,但學過一段時間就忘了,但對intel彙編基礎比較熟悉,兩者使用方法基本相似,所以對著intel彙編,花點時間看at t彙編也就容易了。下面...
Linux C語言內聯彙編使用
最近要改個c語言演算法的關鍵部分用組合語言實現,linux裡嵌入彙編基本使用at t彙編,比如linux系統的啟動部分用的就是at t彙編 以前學過at t彙編,但學過一段時間就忘了,但對intel彙編基礎比較熟悉,兩者使用方法基本相似,所以對著intel彙編,花點時間看at t彙編也就容易了。下面...
AT T學習筆記彙編之內聯c語言
asm assembly code ansi c將asm用於其它用途,用 asm 替換 在asm後面加上 volatile可以禁止編譯器優化 asm volatile pusha n tpopa asm volatile pushl 1 n t 擴充套件asm asm asm code output...