如何通過(guò)asm關(guān)鍵字嵌入?yún)R編語(yǔ)言代碼?
4. test5.c 聲明改動(dòng)的寄存器
在 test4.c 中,我們沒(méi)有聲明改動(dòng)的寄存器,所以編譯器可以任意選擇使用哪些寄存器。從生成的匯編代碼 test4.s 中可以看到,gcc 使用了 %edx 寄存器。
那么我們來(lái)測(cè)試一下:告訴 gcc 不要使用 %edx 寄存器。
#include <stdio.h>
int main()
{
int data1 = 1;
int data2 = 2;
int data3;
asm("movl %%ebx, %%eax "
"addl %%ecx, %%eax"
: "=a"(data3)
: "b"(data1),"c"(data2)
: "%edx");
printf("data3 = %d ", data3);
return 0;
}
代碼中,asm 指令最后部分 "%edx" ,就是用來(lái)告訴 gcc 編譯器:在內(nèi)聯(lián)匯編代碼中,我們會(huì)使用到 %edx 寄存器,你就不要用它了。
生成匯編代碼指令:
gcc -m32 -S -o test5.s test5.c
來(lái)看一下生成的匯編代碼 test5.s:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
movl -20(%ebp), %eax
movl -16(%ebp), %ecx
movl %eax, %ebx
#APP
# 10 "test5.c" 1
movl %ebx, %eax
addl %ecx, %eax
# 0 "" 2
#NO_APP
movl %eax, -12(%ebp)
可以看到,在內(nèi)聯(lián)匯編代碼之前,gcc 沒(méi)有選擇使用寄存器 %edx。
三、使用占位符來(lái)代替寄存器名稱
在上面的示例中,只使用了 2 個(gè)寄存器來(lái)操作 2 個(gè)局部變量,如果操作數(shù)有很多,那么在內(nèi)聯(lián)匯編代碼中去寫每個(gè)寄存器的名稱,就顯得很不方便。
因此,擴(kuò)展 asm 格式為我們提供了另一種偷懶的方法,來(lái)使用輸出和輸入操作數(shù)列表中的寄存器:占位符!
占位符有點(diǎn)類似于批處理腳本中,利用 2...來(lái)引用輸入?yún)?shù)一樣,內(nèi)聯(lián)匯編代碼中的占位符,從輸出操作數(shù)列表中的寄存器開始從 0 編號(hào),一直編號(hào)到輸入操作數(shù)列表中的所有寄存器。
還是看例子比較直接!
1. test6.c 使用占位符代替寄存器#include <stdio.h>
int main()
{
int data1 = 1;
int data2 = 2;
int data3;
asm("addl %1, %2 "
"movl %2, %0"
: "=r"(data3)
: "r"(data1),"r"(data2));
printf("data3 = %d ", data3);
return 0;
}
代碼說(shuō)明:
輸出操作數(shù)列表"=r"(data3):約束使用字符 r, 也就是說(shuō)不指定寄存器,由編譯器來(lái)選擇使用哪個(gè)寄存器來(lái)存儲(chǔ)結(jié)果,最后復(fù)制到局部變量 data3中;
輸入操作數(shù)列表"r"(data1),"r"(data2):約束字符r, 不指定寄存器,由編譯器來(lái)選擇使用哪 2 個(gè)寄存器來(lái)接收局部變量 data1 和 data2;
輸出操作數(shù)列表中只需要一個(gè)寄存器,因此在內(nèi)聯(lián)匯編代碼中的 %0 就代表這個(gè)寄存器(即:從 0 開始計(jì)數(shù));
輸入操作數(shù)列表中有 2 個(gè)寄存器,因此在內(nèi)聯(lián)匯編代碼中的 %1 和 %2 就代表這 2 個(gè)寄存器(即:從輸出操作數(shù)列表的最后一個(gè)寄存器開始順序計(jì)數(shù));
生成匯編代碼指令:
gcc -m32 -S -o test6.s test6.c
匯編代碼如下 test6.s:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
movl -20(%ebp), %eax
movl -16(%ebp), %edx
#APP
# 10 "test6.c" 1
addl %eax, %edx
movl %edx, %eax
# 0 "" 2
#NO_APP
movl %eax, -12(%ebp)
可以看到,gcc 編譯器選擇了 %eax 來(lái)存儲(chǔ)局部變量 data1,%edx 來(lái)存儲(chǔ)局部變量 data2 ,然后操作結(jié)果也存儲(chǔ)在 %eax 寄存器中。
是不是感覺(jué)這樣操作就方便多了?不用我們來(lái)指定使用哪些寄存器,直接交給編譯器來(lái)選擇。
在內(nèi)聯(lián)匯編代碼中,使用 %0、%1 、%2 這樣的占位符來(lái)使用寄存器。
別急,如果您覺(jué)得使用編號(hào)還是麻煩,容易出錯(cuò),還有另一個(gè)更方便的操作:擴(kuò)展 asm 格式還允許給這些占位符重命名,也就是給每一個(gè)寄存器起一個(gè)別名,然后在內(nèi)聯(lián)匯編代碼中使用別名來(lái)操作寄存器。
還是看代碼!
2. test7.c 給寄存器起別名#include <stdio.h>
int main()
{
int data1 = 1;
int data2 = 2;
int data3;
asm("addl %[v1], %[v2] "
"movl %[v2], %[v3]"
: [v3]"=r"(data3)
: [v1]"r"(data1),[v2]"r"(data2));
printf("data3 = %d ", data3);
return 0;
}
代碼說(shuō)明:
輸出操作數(shù)列表:給寄存器(gcc 編譯器選擇的)取了一個(gè)別名 v3;
輸入操作數(shù)列表:給寄存器(gcc 編譯器選擇的)取了一個(gè)別名 v1 和 v2;
起立別名之后,在內(nèi)聯(lián)匯編代碼中就可以直接使用這些別名( %[v1], %[v2], %[v3])來(lái)操作數(shù)據(jù)了。
生成匯編代碼指令:
gcc -m32 -S -o test7.s test7.c
再來(lái)看一下生成的匯編代碼 test7.s:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
movl -20(%ebp), %eax
movl -16(%ebp), %edx
#APP
# 10 "test7.c" 1
addl %eax, %edx
movl %edx, %eax
# 0 "" 2
#NO_APP
movl %eax, -12(%ebp)
這部分的匯編代碼與 test6.s 中完全一樣!
四、使用內(nèi)存位置
在以上的示例中,輸出操作數(shù)列表和輸入操作數(shù)列表部分,使用的都是寄存器(約束字符:a, b, c, d, r等等)。
我們可以指定使用哪個(gè)寄存器,也可以交給編譯器來(lái)選擇使用哪些寄存器,通過(guò)寄存器來(lái)操作數(shù)據(jù),速度會(huì)更快一些。
如果我們?cè)敢獾脑,也可以直接使用變量的?nèi)存地址來(lái)操作變量,此時(shí)就需要使用約束字符 m。
1. test8.c 使用內(nèi)存地址來(lái)操作數(shù)據(jù)#include <stdio.h>
int main()
{
int data1 = 1;
int data2 = 2;
int data3;
asm("movl %1, %%eax "
"addl %2, %%eax "
"movl %%eax, %0"
: "=m"(data3)
: "m"(data1),"m"(data2));
printf("data3 = %d ", data3);
return 0;
}
代碼說(shuō)明:
輸出操作數(shù)列表 "=m"(data3):直接使用變量 data3 的內(nèi)存地址;
輸入操作數(shù)列表 "m"(data1),"m"(data2):直接使用變量 data1, data2 的內(nèi)存地址;
在內(nèi)聯(lián)匯編代碼中,因?yàn)樾枰M(jìn)行相加計(jì)算,因此需要使用一個(gè)寄存器(%eax),計(jì)算這個(gè)環(huán)節(jié)是肯定需要寄存器的。
在操作那些內(nèi)存地址中的數(shù)據(jù)時(shí),使用的仍然是按順序編號(hào)的占位符。
生成匯編代碼指令:
gcc -m32 -S -o test8.s test8.c
生成的匯編代碼如下 test8.s:
movl $1, -24(%ebp)
movl $2, -20(%ebp)
#APP
# 10 "test8.c" 1
movl -24(%ebp), %eax
addl -20(%ebp), %eax
movl %eax, -16(%ebp)
# 0 "" 2
#NO_APP
movl -16(%ebp), %eax
可以看到:在進(jìn)入內(nèi)聯(lián)匯編代碼之前,把 data1 和 data2 的值放在了棧中,然后直接把棧中的數(shù)據(jù)與寄存器 %eax 進(jìn)行操作,最后再把操作結(jié)果(%eax),復(fù)制到棧中 data3 的位置(-16(%ebp))。
五、總結(jié)
通過(guò)以上 8 個(gè)示例,我們把內(nèi)聯(lián)匯編代碼中的關(guān)鍵語(yǔ)法規(guī)則進(jìn)行了講解,有了這個(gè)基礎(chǔ),就可以在內(nèi)聯(lián)匯編代碼中編寫更加復(fù)雜的指令了。
希望以上內(nèi)容對(duì)您能有所幫助!謝謝!

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
7月8日立即報(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ī)器人產(chǎn)業(yè)技術(shù)創(chuàng)新應(yīng)用論壇
-
免費(fèi)參會(huì)立即報(bào)名>> 7月30日- 8月1日 2025全數(shù)會(huì)工業(yè)芯片與傳感儀表展
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍(lán)皮書》
推薦專題
- 1 AI 眼鏡讓百萬(wàn) APP「集體失業(yè)」?
- 2 豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
- 3 一文看懂視覺(jué)語(yǔ)言動(dòng)作模型(VLA)及其應(yīng)用
- 4 “支付+”時(shí)代,支付即生態(tài) | 2025中國(guó)跨境支付十大趨勢(shì)
- 5 中國(guó)最具實(shí)力AI公司TOP10
- 6 特斯拉Robotaxi上路,馬斯克端上畫了十年的餅
- 7 國(guó)家數(shù)據(jù)局局長(zhǎng)劉烈宏調(diào)研格創(chuàng)東智
- 8 AI的夏天:第四范式VS云從科技VS地平線機(jī)器人
- 9 張勇等人退出阿里合伙人
- 10 AI視頻,攪動(dòng)1.5萬(wàn)億市場(chǎng)