如何通過(guò)asm關(guān)鍵字嵌入?yún)R編語(yǔ)言代碼?
一、基本 asm 格式
1. 語(yǔ)法規(guī)則
2. test1.c 插入空指令
3. test2.c 操作全局變量
4. test3.c 嘗試操作局部變量
二、擴(kuò)展 asm 格式
1. 指令格式
2. 輸出和輸入操作數(shù)列表
3. test4.c 通過(guò)寄存器操作局部變量
4. test5.c 聲明使用的寄存器
三、使用占位符來(lái)代替寄存器名稱
1. test6.c 使用占位符代替寄存器名
2. test7.c 給寄存器起別名
四、使用內(nèi)存地址
1. test8.c 使用內(nèi)存地址來(lái)操作數(shù)據(jù)
五、總結(jié)
在 Linux 代碼中,經(jīng)?梢钥吹皆 C 代碼中,嵌入部分匯編代碼,這些代碼要么是與硬件體系相關(guān)的,要么是對(duì)性能有關(guān)鍵影響的。
在很久以前,我特別懼怕內(nèi)嵌匯編代碼,直到后來(lái)把匯編部分的短板補(bǔ)上之后,才徹底終結(jié)這種心理。
也許你在工作中,幾乎不會(huì)涉及到內(nèi)嵌匯編代碼的工作,但是一旦進(jìn)入到系統(tǒng)的底層,或者需要對(duì)時(shí)間關(guān)鍵場(chǎng)景進(jìn)行優(yōu)化,這個(gè)時(shí)候你的知識(shí)儲(chǔ)備就發(fā)揮重要作用了!
這篇文章,我們就來(lái)詳細(xì)聊一聊在 C 語(yǔ)言中,如何通過(guò) asm 關(guān)鍵字來(lái)嵌入?yún)R編語(yǔ)言代碼,文中的 8 個(gè)示例代碼從簡(jiǎn)單到復(fù)雜,逐步深入地介紹內(nèi)聯(lián)匯編的關(guān)鍵語(yǔ)法規(guī)則。
希望這篇文章能夠成為你進(jìn)階高手路上的墊腳石!
PS:
示例代碼中使用的是 Linux 系統(tǒng)中 AT&T 匯編語(yǔ)法;
一、基本 asm 格式
gcc 編譯器支持 2 種形式的內(nèi)聯(lián) asm 代碼:
基本 asm 格式:不支持操作數(shù);
擴(kuò)展 asm 格式:支持操作數(shù);
1. 語(yǔ)法規(guī)則
asm [volatile] ("匯編指令")
所有指令,必須用雙引號(hào)包裹起來(lái);
超過(guò)一條指令,必須用分隔符進(jìn)行分割,為了排版,一般會(huì)加上 ;
多條匯編指令,可以寫在一行,也可以寫在多行;
關(guān)鍵字 asm 可以使用 asm 來(lái)替換;
volatile 是可選的,編譯器有可能對(duì)匯編代碼進(jìn)行優(yōu)化,使用 volatile 關(guān)鍵字之后,告訴編譯器不要優(yōu)化手寫的內(nèi)聯(lián)匯編代碼。
2. test1.c 插入空指令#include <stdio.h>
int main()
{
asm ("nop");
printf("hello");
asm ("nop nop "
"nop");
return 0;
}
注意:C語(yǔ)言中會(huì)自動(dòng)把兩個(gè)連續(xù)的字符串字面量拼接成一個(gè),所以"nop nop " "nop" 這兩個(gè)字符串會(huì)自動(dòng)拼接成一個(gè)字符串。
生成匯編代碼指令:
gcc -m32 -S -o test1.s test1.c
test1.s 中內(nèi)容如下(只貼出了內(nèi)聯(lián)匯編代碼相關(guān)部分的代碼):
#APP
# 5 "test1.c" 1
nop
# 0 "" 2
#NO_APP
// 這里是 printf 語(yǔ)句生成的代碼。
#APP
# 7 "test1.c" 1
nop
nop
nop
# 0 "" 2
#NO_APP
可以看到,內(nèi)聯(lián)匯編代碼被兩個(gè)注釋(#APP ... #NO_APP)包裹起來(lái)。在源碼中嵌入了兩個(gè)匯編代碼,因此可以看到 gcc 編譯器生成的匯編代碼中包含了這兩部分代碼。
這 2 部分嵌入的匯編代碼都是空指令 nop,沒(méi)有什么意義。
3. test2.c 操作全局變量
在 C 代碼中嵌入?yún)R編指令,目的是用來(lái)計(jì)算,或者執(zhí)行一定的功能,下面我們就來(lái)看一下,如何在內(nèi)聯(lián)匯編指令中,操作全局變量。
#include <stdio.h>
int a = 1;
int b = 2;
int c;
int main()
{
asm volatile ("movl a, %eax "
"addl b, %eax "
"movl %eax, c");
printf("c = %d ", c);
return 0;
}
關(guān)于匯編指令中編譯器的基本知識(shí):
eax, ebx 都是 x86 平臺(tái)中的寄存器(32位),在基本asm格式中,寄存器的前面必須加上百分號(hào)%。
32 位的寄存器 eax 可以當(dāng)做 16 位來(lái)使用(ax),或者當(dāng)做 8 位來(lái)使用(ah, al),本文只會(huì)按照 32 位來(lái)使用。
代碼說(shuō)明:
movl a, %eax // 把變量a的值復(fù)制到 %eax 寄存器中;
addl b, %eax // 把變量 b 的值 與 %eax 寄存器中的值(a)相加,結(jié)果放在 %eax 寄存器中;
movl %eax, c // 把 %eax 寄存器中的值復(fù)制到變量 c 中;
生成匯編代碼指令:
gcc -m32 -S -o test2.s test2.c
test2.s 內(nèi)容如下(只貼出與內(nèi)聯(lián)匯編代碼相關(guān)部分):
#APP
# 9 "test2.c" 1
movl a, %eax
addl b, %eax
movl %eax, c
# 0 "" 2
#NO_APP
可以看到,在內(nèi)聯(lián)匯編代碼中,可以直接使用全局變量 a, b 的名稱來(lái)操作。執(zhí)行 test2,可以得到正確的結(jié)果。
思考一個(gè)問(wèn)題:為什么在匯編代碼中,可以使用變量a, b, c?

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
6月20日立即下載>> 【白皮書】精準(zhǔn)測(cè)量 安全高效——福祿克光伏行業(yè)解決方案
-
7月3日立即報(bào)名>> 【在線會(huì)議】英飛凌新一代智能照明方案賦能綠色建筑與工業(yè)互聯(lián)
-
7月22-29日立即報(bào)名>> 【線下論壇】第三屆安富利汽車生態(tài)圈峰會(huì)
-
7.30-8.1火熱報(bào)名中>> 全數(shù)會(huì)2025(第六屆)機(jī)器人及智能工廠展
-
7月31日免費(fèi)預(yù)約>> OFweek 2025具身機(jī)器人動(dòng)力電池技術(shù)應(yīng)用大會(huì)
-
免費(fèi)參會(huì)立即報(bào)名>> 7月30日- 8月1日 2025全數(shù)會(huì)工業(yè)芯片與傳感儀表展
推薦專題
- 1 AI 眼鏡讓百萬(wàn) APP「集體失業(yè)」?
- 2 大廠紛紛入局,百度、阿里、字節(jié)搶奪Agent話語(yǔ)權(quán)
- 3 深度報(bào)告|中國(guó)AI產(chǎn)業(yè)正在崛起成全球力量,市場(chǎng)潛力和關(guān)鍵挑戰(zhàn)有哪些?
- 4 上海跑出80億超級(jí)獨(dú)角獸:獲上市公司戰(zhàn)投,干人形機(jī)器人
- 5 國(guó)家數(shù)據(jù)局局長(zhǎng)劉烈宏調(diào)研格創(chuàng)東智
- 6 下一代入口之戰(zhàn):大廠為何紛紛押注智能體?
- 7 百億AI芯片訂單,瘋狂傾銷中東?
- 8 Robotaxi新消息密集釋放,量產(chǎn)元年誰(shuí)在領(lǐng)跑?
- 9 格斗大賽出圈!人形機(jī)器人致命短板曝光:頭腦過(guò)于簡(jiǎn)單
- 10 “搶灘”家用機(jī)器人領(lǐng)域,聯(lián)通、海爾、美的等紛紛入局