如何通過asm關(guān)鍵字嵌入?yún)R編語言代碼?
查看 test2.s 中內(nèi)聯(lián)匯編代碼之前的部分,可以看到:
.file "test2.c"
.globl a
.data
.a(chǎn)lign 4
.type a, @object
.size a, 4
a:
.long 1
.globl b
.a(chǎn)lign 4
.type b, @object
.size b, 4
b:
.long 2
.comm c,4,4
變量 a, b 被 .globl 修飾,c 被 .comm 修飾,相當(dāng)于是把它們導(dǎo)出為全局的,所以可以在匯編代碼中使用。
那么問題來了:如果是一個局部變量,在匯編代代碼中就不會用 .globl 導(dǎo)出,此時在內(nèi)聯(lián)匯編指令中,還可以直接使用嗎?
眼見為實(shí),我們把這 3 個變量放到 main 函數(shù)的內(nèi)部,作為局部變量來試一下。
4. test3.c 嘗試操作局部變量#include <stdio.h>
int main()
{
int a = 1;
int b = 2;
int c;
asm("movl a, %eax "
"addl b, %eax "
"movl %eax, c");
printf("c = %d ", c);
return 0;
}
生成匯編代碼指令:
gcc -m32 -S -o test3.s test3.c
在 test3.s 中可以看到?jīng)]有 a, b, c 的導(dǎo)出符號,a 和 b 沒有其他地方使用,因此直接把他們的數(shù)值復(fù)制到?臻g中了:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
我們來嘗試編譯成可執(zhí)行程序:
$ gcc -m32 -o test3 test3.c
/tmp/ccuY0TOB.o: In function `main':
test3.c:(.text+0x20): undefined reference to `a'
test3.c:(.text+0x26): undefined reference to `b'
test3.c:(.text+0x2b): undefined reference to `c'
collect2: error: ld returned 1 exit status
編譯報(bào)錯:找不到對 a,b,c 的引用!那該怎么辦,才能使用局部變量呢?擴(kuò)展 asm 格式!
二、擴(kuò)展 asm 格式
1. 指令格式
asm [volatile] ("匯編指令" : "輸出操作數(shù)列表" : "輸入操作數(shù)列表" : "改動的寄存器")
格式說明
匯編指令:與基本asm格式相同;
輸出操作數(shù)列表:匯編代碼如何把處理結(jié)果傳遞到 C 代碼中;
輸入操作數(shù)列表:C 代碼如何把數(shù)據(jù)傳遞給內(nèi)聯(lián)匯編代碼;
改動的寄存器:告訴編譯器,在內(nèi)聯(lián)匯編代碼中,我們使用了哪些寄存器;
“改動的寄存器”可以省略,此時最后一個冒號可以不要,但是前面的冒號必須保留,即使輸出/輸入操作數(shù)列表為空。
關(guān)于“改動的寄存器”再解釋一下:gcc 在編譯 C 代碼的時候,需要使用一系列寄存器;我們手寫的內(nèi)聯(lián)匯編代碼中,也使用了一些寄存器。
為了通知編譯器,讓它知道: 在內(nèi)聯(lián)匯編代碼中有哪些寄存器被我們用戶使用了,可以在這里列舉出來,這樣的話,gcc 就會避免使用這些列舉出的寄存器
2. 輸出和輸入操作數(shù)列表的格式
在系統(tǒng)中,存儲變量的地方就2個:寄存器和內(nèi)存。因此,告訴內(nèi)聯(lián)匯編代碼輸出和輸入操作數(shù),其實(shí)就是告訴它:
向哪些寄存器或內(nèi)存地址輸出結(jié)果;
從哪些寄存器或內(nèi)存地址讀取輸入數(shù)據(jù);
這個過程也要滿足一定的格式:
"[輸出修飾符]約束"(寄存器或內(nèi)存地址)
(1)約束
就是通過不同的字符,來告訴編譯器使用哪些寄存器,或者內(nèi)存地址。包括下面這些字符:
a: 使用 eax/ax/al 寄存器;
b: 使用 ebx/bx/bl 寄存器;
c: 使用 ecx/cx/cl 寄存器;
d: 使用 edx/dx/dl 寄存器;
r: 使用任何可用的通用寄存器;
m: 使用變量的內(nèi)存位置;
先記住這幾個就夠用了,其他的約束選項(xiàng)還有:D, S, q, A, f, t, u等等,需要的時候再查看文檔。
(2)輸出修飾符
顧名思義,它使用來修飾輸出的,對輸出寄存器或內(nèi)存地址提供額外的說明,包括下面4個修飾符:
+:被修飾的操作數(shù)可以讀取,可以寫入;
=:被修飾的操作數(shù)只能寫入;
%:被修飾的操作數(shù)可以和下一個操作數(shù)互換;
&:在內(nèi)聯(lián)函數(shù)完成之前,可以刪除或者重新使用被修飾的操作數(shù);
語言描述比較抽象,直接看例子!
3. test4.c 通過寄存器操作局部變量#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));
printf("data3 = %d ", data3);
return 0;
}
有 2 個地方需要注意一下啊:
在內(nèi)聯(lián)匯編代碼中,沒有聲明“改動的寄存器”列表,也就是說可以省略掉(前面的冒號也不需要);
擴(kuò)展asm格式中,寄存器前面必須寫 2 個%;
代碼解釋:
"b"(data1),"c"(data2) ==> 把變量 data1 復(fù)制到寄存器 %ebx,變量 data2 復(fù)制到寄存器 %ecx。這樣,內(nèi)聯(lián)匯編代碼中,就可以通過這兩個寄存器來操作這兩個數(shù)了;
"=a"(data3) ==> 把處理結(jié)果放在寄存器 %eax 中,然后復(fù)制給變量data3。前面的修飾符等號意思是:會寫入往 %eax 中寫入數(shù)據(jù),不會從中讀取數(shù)據(jù);
通過上面的這種格式,內(nèi)聯(lián)匯編代碼中,就可以使用指定的寄存器來操作局部變量了,稍后將會看到局部變量是如何從經(jīng)過棧空間,復(fù)制到寄存器中的。
生成匯編代碼指令:
gcc -m32 -S -o test4.s test4.c
匯編代碼 test4.s 如下:
movl $1, -20(%ebp)
movl $2, -16(%ebp)
movl -20(%ebp), %eax
movl -16(%ebp), %edx
movl %eax, %ebx
movl %edx, %ecx
#APP
# 10 "test4.c" 1
movl %ebx, %eax
addl %ecx, %eax
# 0 "" 2
#NO_APP
movl %eax, -12(%ebp)
可以看到,在進(jìn)入手寫的內(nèi)聯(lián)匯編代碼之前:
把數(shù)字 1 通過?臻g(-20(%ebp)),復(fù)制到寄存器 %eax,再復(fù)制到寄存器 %ebx;
把數(shù)字 2 通過棧空間(-16(%ebp)),復(fù)制到寄存器 %edx,再復(fù)制到寄存器 %ecx;
這 2 個操作正是對應(yīng)了內(nèi)聯(lián)匯編代碼中的“輸入操作數(shù)列表”部分:"b"(data1),"c"(data2)。
在內(nèi)聯(lián)匯編代碼之后(#NO_APP 之后),把 %eax 寄存器中的值復(fù)制到棧中的 -12(%ebp) 位置,這個位置正是局部變量 data3 所在的位置,這樣就完成了輸出操作。

發(fā)表評論
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
10月23日火熱報(bào)名中>> 2025是德科技創(chuàng)新技術(shù)峰會
-
10月23日立即報(bào)名>> Works With 開發(fā)者大會深圳站
-
10月24日立即參評>> 【評選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評選
-
即日-11.25立即下載>>> 費(fèi)斯托白皮書《柔性:汽車生產(chǎn)未來的關(guān)鍵》
-
11月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會
-
12月18日立即報(bào)名>> 【線下會議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
推薦專題
-
10 大模型的盡頭是開源
- 1 特斯拉工人被故障機(jī)器人打成重傷,索賠3.6億
- 2 【行業(yè)深度研究】退居幕后四年后,張一鳴終于把算法公司變成AI公司?
- 3 AI 時代,阿里云想當(dāng)“安卓” ,那誰是“蘋果”?
- 4 華為公布昇騰芯片三年計(jì)劃,自研HBM曝光
- 5 硬剛英偉達(dá)!華為發(fā)布全球最強(qiáng)算力超節(jié)點(diǎn)和集群
- 6 機(jī)器人9月大事件|3家國產(chǎn)機(jī)器人沖刺IPO,行業(yè)交付與融資再創(chuàng)新高!
- 7 谷歌“香蕉”爆火啟示:國產(chǎn)垂類AI的危機(jī)還是轉(zhuǎn)機(jī)?
- 8 00后華裔女生靠兩部AI電影狂賺7.8億人民幣,AI正式進(jìn)軍好萊塢
- 9 美光:AI Capex瘋投不止,終于要拉起存儲超級周期了?
- 10 華為已殺入!AI領(lǐng)域最熱黃金賽道,大廠的數(shù)字人美女讓我一夜沒睡著覺