如何通過asm關鍵字嵌入?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 修飾,相當于是把它們導出為全局的,所以可以在匯編代碼中使用。
那么問題來了:如果是一個局部變量,在匯編代代碼中就不會用 .globl 導出,此時在內(nèi)聯(lián)匯編指令中,還可以直接使用嗎?
眼見為實,我們把這 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 的導出符號,a 和 b 沒有其他地方使用,因此直接把他們的數(shù)值復制到棧空間中了:
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
編譯報錯:找不到對 a,b,c 的引用!那該怎么辦,才能使用局部變量呢?擴展 asm 格式!
二、擴展 asm 格式
1. 指令格式
asm [volatile] ("匯編指令" : "輸出操作數(shù)列表" : "輸入操作數(shù)列表" : "改動的寄存器")
格式說明
匯編指令:與基本asm格式相同;
輸出操作數(shù)列表:匯編代碼如何把處理結(jié)果傳遞到 C 代碼中;
輸入操作數(shù)列表:C 代碼如何把數(shù)據(jù)傳遞給內(nèi)聯(lián)匯編代碼;
改動的寄存器:告訴編譯器,在內(nèi)聯(lián)匯編代碼中,我們使用了哪些寄存器;
“改動的寄存器”可以省略,此時最后一個冒號可以不要,但是前面的冒號必須保留,即使輸出/輸入操作數(shù)列表為空。
關于“改動的寄存器”再解釋一下:gcc 在編譯 C 代碼的時候,需要使用一系列寄存器;我們手寫的內(nèi)聯(lián)匯編代碼中,也使用了一些寄存器。
為了通知編譯器,讓它知道: 在內(nèi)聯(lián)匯編代碼中有哪些寄存器被我們用戶使用了,可以在這里列舉出來,這樣的話,gcc 就會避免使用這些列舉出的寄存器
2. 輸出和輸入操作數(shù)列表的格式
在系統(tǒng)中,存儲變量的地方就2個:寄存器和內(nèi)存。因此,告訴內(nèi)聯(lián)匯編代碼輸出和輸入操作數(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)存位置;
先記住這幾個就夠用了,其他的約束選項還有: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)匯編代碼中,沒有聲明“改動的寄存器”列表,也就是說可以省略掉(前面的冒號也不需要);
擴展asm格式中,寄存器前面必須寫 2 個%;
代碼解釋:
"b"(data1),"c"(data2) ==> 把變量 data1 復制到寄存器 %ebx,變量 data2 復制到寄存器 %ecx。這樣,內(nèi)聯(lián)匯編代碼中,就可以通過這兩個寄存器來操作這兩個數(shù)了;
"=a"(data3) ==> 把處理結(jié)果放在寄存器 %eax 中,然后復制給變量data3。前面的修飾符等號意思是:會寫入往 %eax 中寫入數(shù)據(jù),不會從中讀取數(shù)據(jù);
通過上面的這種格式,內(nèi)聯(lián)匯編代碼中,就可以使用指定的寄存器來操作局部變量了,稍后將會看到局部變量是如何從經(jīng)過?臻g,復制到寄存器中的。
生成匯編代碼指令:
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)
可以看到,在進入手寫的內(nèi)聯(lián)匯編代碼之前:
把數(shù)字 1 通過?臻g(-20(%ebp)),復制到寄存器 %eax,再復制到寄存器 %ebx;
把數(shù)字 2 通過?臻g(-16(%ebp)),復制到寄存器 %edx,再復制到寄存器 %ecx;
這 2 個操作正是對應了內(nèi)聯(lián)匯編代碼中的“輸入操作數(shù)列表”部分:"b"(data1),"c"(data2)。
在內(nèi)聯(lián)匯編代碼之后(#NO_APP 之后),把 %eax 寄存器中的值復制到棧中的 -12(%ebp) 位置,這個位置正是局部變量 data3 所在的位置,這樣就完成了輸出操作。
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-10.29立即報名>> 2024德州儀器嵌入式技術(shù)創(chuàng)新發(fā)展研討會
-
10月31日立即下載>> 【限時免費下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月14日立即報名>> 2024工程師系列—工業(yè)電子技術(shù)在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
推薦專題
-
10 百度搜索,正在被平替
- 1 Intel宣布40年來最重大轉(zhuǎn)型:年底前裁員15000人、拋掉2/3房產(chǎn)
- 2 因美封殺TikTok,字節(jié)股價骨折!估值僅Meta1/5
- 3 宏山激光重磅發(fā)布行業(yè)解決方案,助力智能制造產(chǎn)業(yè)新飛躍
- 4 國產(chǎn)AI芯片公司破產(chǎn)!白菜價拍賣
- 5 具身智能火了,但規(guī)模落地還需時間
- 6 三次錯失風口!OpenAI前員工殺回AI編程賽道,老東家捧金相助
- 7 國產(chǎn)英偉達們,抓緊沖刺A股
- 8 英特爾賦能智慧醫(yī)療,共創(chuàng)數(shù)字化未來
- 9 英偉達的麻煩在后頭?
- 10 將“網(wǎng)紅”變成“商品”,AI“爆改”實力拉滿
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市