国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

內聯匯編很可難嗎 看完這篇文章就能搞定!

Q4MP_gh_c472c21 ? 來源:IOT物聯網小鎮 ? 作者:道哥 ? 2021-04-29 13:57 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、基本 asm 格式

1. 語法規則

2.test1.c 插入空指令

3. test2.c操作全局變量

4. test3.c 嘗試操作局部變量

二、擴展 asm 格式

1. 指令格式

2.輸出和輸入操作數列表

3.test4.c通過寄存器操作局部變量

4. test5.c聲明使用的寄存器

三、使用占位符來代替寄存器名稱

1. test6.c使用占位符代替寄存器名

2. test7.c 給寄存器起別名

四、使用內存地址

1.test8.c 使用內存地址來操作數據

五、總結

Linux 代碼中,經常可以看到在 C 代碼中,嵌入部分匯編代碼,這些代碼要么是與硬件體系相關的,要么是對性能有關鍵影響的。

在很久以前,我特別懼怕內嵌匯編代碼,直到后來把匯編部分的短板補上之后,才徹底終結這種心理。

也許你在工作中,幾乎不會涉及到內嵌匯編代碼的工作,但是一旦進入到系統的底層,或者需要對時間關鍵場景進行優化,這個時候你的知識儲備就發揮重要作用了!

這篇文章,我們就來詳細聊一聊在 C 語言中,如何通過asm 關鍵字來嵌入匯編語言代碼,文中的 8 個示例代碼從簡單到復雜,逐步深入地介紹內聯匯編的關鍵語法規則。

希望這篇文章能夠成為你進階高手路上的墊腳石!

PS:

示例代碼中使用的是 Linux 系統中 AT&T 匯編語法;

文章中的 8 個示例代碼,可以在公眾號后臺回復【426】,即可收到下載地址;

一、基本 asm 格式

gcc 編譯器支持2 種形式的內聯 asm 代碼:

基本 asm 格式:不支持操作數;

擴展 asm 格式:支持操作數;

1. 語法規則

asm [volatile] ("匯編指令")

所有指令,必須用雙引號包裹起來;

超過一條指令,必須用 分隔符進行分割,為了排版,一般會加上 ;

多條匯編指令,可以寫在一行,也可以寫在多行;

關鍵字 asm 可以使用asm來替換;

volatile 是可選的,編譯器有可能對匯編代碼進行優化,使用 volatile 關鍵字之后,告訴編譯器不要優化手寫的內聯匯編代碼。

2. test1.c 插入空指令

#include 
int main()
{
    asm ("nop");
    printf("hello
");
    asm ("nop
	nop
	"
 "nop");
    return 0;
}

注意:C語言中會自動把兩個連續的字符串字面量拼接成一個,所以"nop nop " "nop"這兩個字符串會自動拼接成一個字符串。

生成匯編代碼指令:

gcc -m32 -S -o test1.s test1.c

test1.s 中內容如下(只貼出了內聯匯編代碼相關部分的代碼):

#APP
# 5 "test1.c" 1
nop
# 0 "" 2
#NO_APP
// 這里是 printf 語句生成的代碼。
#APP
# 7 "test1.c" 1
nop
nop
nop
# 0 "" 2
#NO_APP

可以看到,內聯匯編代碼被兩個注釋(#APP ... #NO_APP)包裹起來。在源碼中嵌入了兩個匯編代碼,因此可以看到 gcc 編譯器生成的匯編代碼中包含了這兩部分代碼。

這 2 部分嵌入的匯編代碼都是空指令 nop,沒有什么意義。

3. test2.c 操作全局變量

在 C 代碼中嵌入匯編指令,目的是用來計算,或者執行一定的功能,下面我們就來看一下,如何在內聯匯編指令中,操作全局變量。

#include 

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;
}

關于匯編指令中編譯器的基本知識:

eax, ebx 都是 x86 平臺中的寄存器(32位),在基本asm格式中,寄存器的前面必須加上百分號%。

32 位的寄存器eax可以當做 16 位來使用(ax),或者當做 8 位來使用(ah, al),本文只會按照 32 位來使用。

代碼說明:

movl a, %eax // 把變量a的值復制到 %eax 寄存器中;

addl b, %eax // 把變量 b 的值 與 %eax 寄存器中的值(a)相加,結果放在 %eax 寄存器中;

movl %eax, c // 把 %eax 寄存器中的值復制到變量 c 中;

3f087b10-a86f-11eb-9728-12bb97331649.png

生成匯編代碼指令:

gcc -m32 -S -o test2.s test2.c

test2.s 內容如下(只貼出與內聯匯編代碼相關部分):

#APP

# 9 "test2.c" 1
movl a, %eax
addl b, %eax
movl %eax, c
# 0 "" 2
#NO_APP

可以看到,在內聯匯編代碼中,可以直接使用全局變量 a, b 的名稱來操作。執行 test2,可以得到正確的結果。

思考一個問題:為什么在匯編代碼中,可以使用變量a, b, c?

查看 test2.s 中內聯匯編代碼之前的部分,可以看到:

.file"test2.c"
.globla
.data
.align 4
.typea, @object
.sizea, 4
a:
.long1
.globlb
.align 4
.typeb, @object
.sizeb, 4
b:
.long2
.commc,4,4

變量 a, b 被 .globl 修飾,c 被 .comm 修飾,相當于是把它們導出為全局的,所以可以在匯編代碼中使用。

那么問題來了:如果是一個局部變量,在匯編代代碼中就不會用 .globl 導出,此時在內聯匯編指令中,還可以直接使用嗎?

眼見為實,我們把這 3 個變量放到 main 函數的內部,作為局部變量來試一下。

4. test3.c 嘗試操作局部變量

#include 
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 中可以看到沒有a, b, c 的導出符號,a 和 b 沒有其他地方使用,因此直接把他們的數值復制到??臻g中了:

movl$1, -20(%ebp)
movl$2, -16(%ebp)

40e39028-a86f-11eb-9728-12bb97331649.png

我們來嘗試編譯成可執行程序:

$ gcc -m32 -o test3 test3.c
/tmp/ccuY0TOB.o: In function `main':
test3.c undefined reference to `a'
test3.c undefined reference to `b'
test3.c undefined reference to `c'
collect2: error: ld returned 1 exit status

編譯報錯:找不到對 a,b,c 的引用!那該怎么辦,才能使用局部變量呢?擴展 asm 格式!

二、擴展 asm 格式

1. 指令格式

asm [volatile] ("匯編指令" : "輸出操作數列表" : "輸入操作數列表" : "改動的寄存器")

格式說明

匯編指令:與基本asm格式相同;

輸出操作數列表:匯編代碼如何把處理結果傳遞到 C 代碼中;

輸入操作數列表:C 代碼如何把數據傳遞給內聯匯編代碼;

改動的寄存器:告訴編譯器,在內聯匯編代碼中,我們使用了哪些寄存器;

“改動的寄存器”可以省略,此時最后一個冒號可以不要,但是前面的冒號必須保留,即使輸出/輸入操作數列表為空。

關于“改動的寄存器”再解釋一下:gcc 在編譯 C 代碼的時候,需要使用一系列寄存器;我們手寫的內聯匯編代碼中,也使用了一些寄存器。

為了通知編譯器,讓它知道:在內聯匯編代碼中有哪些寄存器被我們用戶使用了,可以在這里列舉出來,這樣的話,gcc 就會避免使用這些列舉出的寄存器

2. 輸出和輸入操作數列表的格式

在系統中,存儲變量的地方就2個:寄存器和內存。因此,告訴內聯匯編代碼輸出和輸入操作數,其實就是告訴它:

向哪些寄存器或內存地址輸出結果;

從哪些寄存器或內存地址讀取輸入數據;

這個過程也要滿足一定的格式:

"[輸出修飾符]約束"(寄存器或內存地址)

(1)約束

就是通過不同的字符,來告訴編譯器使用哪些寄存器,或者內存地址。包括下面這些字符:

a: 使用 eax/ax/al 寄存器;

b: 使用 ebx/bx/bl 寄存器;

c: 使用 ecx/cx/cl 寄存器;

d: 使用 edx/dx/dl 寄存器;

r: 使用任何可用的通用寄存器;

m: 使用變量的內存位置;

先記住這幾個就夠用了,其他的約束選項還有:D, S, q, A, f, t, u等等,需要的時候再查看文檔。

(2)輸出修飾符

顧名思義,它使用來修飾輸出的,對輸出寄存器或內存地址提供額外的說明,包括下面4個修飾符:

+:被修飾的操作數可以讀取,可以寫入;

=:被修飾的操作數只能寫入;

%:被修飾的操作數可以和下一個操作數互換;

&:在內聯函數完成之前,可以刪除或者重新使用被修飾的操作數;

語言描述比較抽象,直接看例子!

3. test4.c 通過寄存器操作局部變量

#include 

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 個地方需要注意一下?。?/p>

在內聯匯編代碼中,沒有聲明“改動的寄存器”列表,也就是說可以省略掉(前面的冒號也不需要);

擴展asm格式中,寄存器前面必須寫 2 個%;

代碼解釋:

"b"(data1),"c"(data2) ==> 把變量 data1 復制到寄存器 %ebx,變量 data2 復制到寄存器 %ecx。這樣,內聯匯編代碼中,就可以通過這兩個寄存器來操作這兩個數了;

"=a"(data3) ==> 把處理結果放在寄存器 %eax 中,然后復制給變量data3。前面的修飾符等號意思是:會寫入往 %eax 中寫入數據,不會從中讀取數據;

通過上面的這種格式,內聯匯編代碼中,就可以使用指定的寄存器來操作局部變量了,稍后將會看到局部變量是如何從經過??臻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)

411b1994-a86f-11eb-9728-12bb97331649.png

可以看到,在進入手寫的內聯匯編代碼之前:

把數字 1 通過棧空間(-20(%ebp)),復制到寄存器 %eax,再復制到寄存器 %ebx;

把數字 2 通過??臻g(-16(%ebp)),復制到寄存器 %edx,再復制到寄存器 %ecx;

這 2 個操作正是對應了內聯匯編代碼中的“輸入操作數列表”部分:"b"(data1),"c"(data2)。

在內聯匯編代碼之后(#NO_APP 之后),把%eax寄存器中的值復制到棧中的-12(%ebp)位置,這個位置正是局部變量 data3所在的位置,這樣就完成了輸出操作。

4. test5.c 聲明改動的寄存器

在 test4.c 中,我們沒有聲明改動的寄存器,所以編譯器可以任意選擇使用哪些寄存器。從生成的匯編代碼 test4.s 中可以看到,gcc 使用了%edx寄存器。

那么我們來測試一下:告訴 gcc 不要使用 %edx 寄存器。

#include 
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",就是用來告訴 gcc 編譯器:在內聯匯編代碼中,我們會使用到 %edx 寄存器,你就不要用它了。

生成匯編代碼指令:

gcc -m32 -S -o test5.s test5.c

來看一下生成的匯編代碼 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)

415f4d94-a86f-11eb-9728-12bb97331649.png

可以看到,在內聯匯編代碼之前,gcc沒有選擇使用寄存器%edx。

三、使用占位符來代替寄存器名稱

在上面的示例中,只使用了2 個寄存器來操作 2 個局部變量,如果操作數有很多,那么在內聯匯編代碼中去寫每個寄存器的名稱,就顯得很不方便。

因此,擴展 asm 格式為我們提供了另一種偷懶的方法,來使用輸出和輸入操作數列表中的寄存器:占位符!

占位符有點類似于批處理腳本中,利用2...來引用輸入參數一樣,內聯匯編代碼中的占位符,從輸出操作數列表中的寄存器開始從0編號,一直編號到輸入操作數列表中的所有寄存器。

還是看例子比較直接!

1. test6.c 使用占位符代替寄存器

#include 
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;
}

代碼說明:

輸出操作數列表"=r"(data3):約束使用字符 r, 也就是說不指定寄存器,由編譯器來選擇使用哪個寄存器來存儲結果,最后復制到局部變量 data3中;

輸入操作數列表"r"(data1),"r"(data2):約束字符r, 不指定寄存器,由編譯器來選擇使用哪 2 個寄存器來接收局部變量 data1 和 data2;

輸出操作數列表中只需要一個寄存器,因此在內聯匯編代碼中的 %0 就代表這個寄存器(即:從 0 開始計數);

輸入操作數列表中有 2 個寄存器,因此在內聯匯編代碼中的 %1 和 %2就代表這 2 個寄存器(即:從輸出操作數列表的最后一個寄存器開始順序計數);

生成匯編代碼指令:

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)

422d3ac4-a86f-11eb-9728-12bb97331649.png

可以看到,gcc 編譯器選擇了%eax來存儲局部變量 data1,%edx來存儲局部變量 data2,然后操作結果也存儲在%eax 寄存器中。

是不是感覺這樣操作就方便多了?不用我們來指定使用哪些寄存器,直接交給編譯器來選擇。

在內聯匯編代碼中,使用%0、%1 、%2這樣的占位符來使用寄存器。

別急,如果您覺得使用編號還是麻煩,容易出錯,還有另一個更方便的操作:擴展 asm 格式還允許給這些占位符重命名,也就是給每一個寄存器起一個別名,然后在內聯匯編代碼中使用別名來操作寄存器。

還是看代碼!

2. test7.c 給寄存器起別名

#include 
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;
}

代碼說明:

輸出操作數列表:給寄存器(gcc 編譯器選擇的)取了一個別名 v3;

輸入操作數列表:給寄存器(gcc 編譯器選擇的)取了一個別名 v1 和 v2;

起立別名之后,在內聯匯編代碼中就可以直接使用這些別名( %[v1], %[v2], %[v3])來操作數據了。

生成匯編代碼指令:

gcc -m32 -S -o test7.s test7.c

再來看一下生成的匯編代碼 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 中完全一樣!

四、使用內存位置

在以上的示例中,輸出操作數列表和輸入操作數列表部分,使用的都是寄存器(約束字符:a, b, c, d, r等等)。

我們可以指定使用哪個寄存器,也可以交給編譯器來選擇使用哪些寄存器,通過寄存器來操作數據,速度會更快一些。

如果我們愿意的話,也可以直接使用變量的內存地址來操作變量,此時就需要使用約束字符 m。

1. test8.c 使用內存地址來操作數據

#include 
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;
}

代碼說明:

輸出操作數列表 "=m"(data3):直接使用變量 data3 的內存地址;

輸入操作數列表 "m"(data1),"m"(data2):直接使用變量 data1, data2 的內存地址;

在內聯匯編代碼中,因為需要進行相加計算,因此需要使用一個寄存器(%eax),計算這個環節是肯定需要寄存器的。

在操作那些內存地址中的數據時,使用的仍然是按順序編號的占位符。

生成匯編代碼指令:

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

425d8d64-a86f-11eb-9728-12bb97331649.png

可以看到:在進入內聯匯編代碼之前,把data1 和 data2的值放在了棧中,然后直接把棧中的數據與寄存器%eax進行操作,最后再把操作結果(%eax),復制到棧中data3 的位置(-16(%ebp))。

五、總結

通過以上 8 個示例,我們把內聯匯編代碼中的關鍵語法規則進行了講解,有了這個基礎,就可以在內聯匯編代碼中編寫更加復雜的指令了。

希望以上內容對您能有所幫助!謝謝!

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5608

    瀏覽量

    129968
  • ASM
    ASM
    +關注

    關注

    1

    文章

    69

    瀏覽量

    19884
  • 代碼
    +關注

    關注

    30

    文章

    4968

    瀏覽量

    73960
  • 編譯器
    +關注

    關注

    1

    文章

    1672

    瀏覽量

    51600

原文標題:內聯匯編很可怕嗎?看完這篇文章,終結它!

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    內聯函數介紹

    內聯函數禁用所有的編譯選項。使用__inline修飾函數導致函數在調用處直接替換為函數體。這樣代碼調用函數更快,但增加代碼的大小,特別在函數本身比較大而且經常調用的情況下。 __inline
    發表于 12-12 07:08

    inline ASM(內聯匯編)的細節分享

    內聯匯編? 基本的語法 asm volatile (\"instruction list\":OUTPUT:INPUT:(clobber/modify)); 如果
    發表于 10-31 09:11

    C內聯匯編nice指令解讀

    一、指令基本結構 支持類型:只支持R型 NameopcodetypeCUSTOM07'h0bR type CUSTOM17'h2bR tpye CUSTOM27'h5bR type CUSTOM37'h7bR type1.costom3 lbuf(a1): 加載內存中的數據至row_buf : ? .insn r opcode,func3,func7,rd,rs1,rs2 2.costom3 sbuf(a1): 保存數據row_buf的數據至內存: ? .insn r opcode,func3,func7,rd,rs1,rs2 3.costom3 acc rowsum: 加載a1地址的數據,累加row 數據并寫回: rowsum rd,a1,x0 ? .insn r opcode,func3,func7,rd,rs1,rs2 二、示例分析 1.custom_lbuf ".insn r 0x7b, 2, 1, x0, %1, x0" :"=r"(zero) :"r"(addr) 字母“r”表示使用編譯器自動分配的寄存器來存儲該操作數變量;字母“m” 表示使用內存地址來存儲該操作數變量。如果同時指明“rm”,則編譯器自動選擇最優方案。。 對于“輸出操作數”而言,等號“=”代表輸出變量用作輸出,原來的值會被新值替換;“+”代表輸出變量不僅作為輸出,而且作為輸入。 opcodefunc3func7rdrs1rs20x7b21x0%1x0 custom3只讀取rs1的數據第一種操作零寄存器保存addr地址零寄存器 11110110100000001000000101000000 機器碼: funct7rs2rs1funct3rdopcode00000010000001010010000001111011 把addr的地址加載到源寄存器1,編譯器會自動分配rs1用哪一個寄存器(這里是x10),執行lbuf操作,將數據導入nice_core。 2.custom_sbuf ".insn r 0x7b, 2, 2, x0, %1, x0" :"=r"(zero) :"r"(addr) opcodefunc3func7rdrs1rs20x7b22x0%1x0 custom3只讀取rs1的數據第二種操作零寄存器保存addr地址零寄存器 11110110100000010000000101000000機器碼: funct7rs2rs1funct3rdopcode00000100000001010010000001111011 把addr的地址加載到源寄存器1,編譯器會自動分配rs1用哪一個寄存器(這里是x10),執行sbuf操作,將nice_core的數據導出addr。 3.custom_rowsum ".insn r 0x7b, 6, 6, %0, %1, x0" :"=r"(rowsum) :"r"(addr) opcodefunc3func7rdrs1rs20x7b66%0%1x0 custom3讀取rs1、rd的數據第六種操作rowsum地址保存addr地址零寄存器 11110111100000110010110101000000機器碼: funct7rs2rs1funct3rdopcode00001100000001010110010111111011把addr、rd的地址加載到讀源寄存器1,寫目標寄存器rd,編譯器會自動分配rs1,rd用哪一個寄存器(這里是x10、x11),執行sumrow操作。 附 riscv 寄存器編號:
    發表于 10-31 08:31

    內聯匯編的妙用

    它數據相關,于是借助循環變量i,做累加操作,但結果還是不對。 3、內聯匯編(結果正確) 一覺醒來,突然想到內聯匯編,決定一試:既然編譯器不能如我所愿,那可以把想要的部分先自己編譯。
    發表于 10-31 06:28

    簡單的內聯匯編介紹

    ,只能采用內嵌匯編指令(CSR指令)的方式,才能對 CSR 寄存器進行操作。 內聯匯編程序 內斂匯編函數格式: asm volatile ( 匯編
    發表于 10-30 08:04

    RISC-V的工具鏈GCC內聯匯編

    GCC內聯匯編語法規則如下: asmvolatile( 匯編指令列表 :輸出操作數 :輸入操作數 :可能影響的寄存器或存儲器); 以下分別詳細介紹: 1.關鍵詞“asm”是GCC的關鍵詞,表示進行
    發表于 10-30 06:59

    蜂鳥自定義指令軟件講解和內聯匯編(一)

    內聯匯編介紹 asm volatile(“.insn r 0x7b, 2, 1, x0, %1, x0” : “=r”(zero) : “r”(addr)); (1)GCC內聯匯編
    發表于 10-24 10:51

    GCC內聯匯編

    GCC內聯匯編 在蜂鳥內核的NICE協處理器擴展demo的insn.h文件中存在下面一段指令,用于定義對協處理器調用指令,demo中協處理器支持三條指令:lbuf從內存中load數據至行數據緩存
    發表于 10-24 07:46

    通過內聯匯編調用乘法指令mulh\\mulhsu\\mulhu

    mulh、mulhu與mulhsu指令,不能直接驗證,需要其他方法。因此,我們想到了在C語言中嵌入內聯匯編,分別生成三條指令的接口函數,之后便只需在C語言中調用者三中函數便可執行mulh、mulhu
    發表于 10-24 06:52

    浮點運算單元的實現——浮點指令內聯匯編(一)

    代碼實現 在硬件實現FPU后,可通過內聯匯編的方式,指定浮點指令對其進行測試,以下羅列出相關測試代碼。 //fmadds_test __STATIC_FORCEINLINE float
    發表于 10-23 06:51

    浮點運算單元的實現——浮點指令內聯匯編(二)

    代碼實現 在硬件實現FPU后,可通過內聯匯編的方式,指定浮點指令對其進行測試,以下羅列出相關測試代碼。如有錯誤,歡迎大家評論指出。 //feqs_test
    發表于 10-23 06:17

    浮點運算單元的實現——浮點指令內聯匯編(三)

    代碼實現 在編寫完浮點指令相關的內聯函數后,參考nice_demo的例子,將其全放在一個頭文件中,并編寫浮點指令測試代碼,代碼和結果如下。如有錯誤,歡迎大家評論指出。 主函數代碼 int
    發表于 10-22 08:08

    宏集HMI-4G套裝,輕松搞定“數據上云+異地遠程運維”

    工業現場設備分散、環境復雜、網絡部署?宏集 HMI-4G 套裝一站搞定!輕松打破數據孤島,實現數據上云與遠程運維。文末附有真實客戶案例,歡迎查閱參考。
    的頭像 發表于 08-14 16:46 ?1062次閱讀
    宏集HMI-4G套裝,輕松<b class='flag-5'>搞定</b>“數據上云+異地遠程運維”

    C語言中的內聯函數與宏

    在C編程中,內聯函數和宏都用于避免函數調用的開銷并編寫可復用的邏輯部分,但它們在工作方式和安全性方面存在顯著差異。
    的頭像 發表于 07-25 15:10 ?1909次閱讀
    C語言中的<b class='flag-5'>內聯</b>函數與宏

    MSP430常用內聯函數說明

    電子發燒友網站提供《MSP430常用內聯函數說明.docx》資料免費下載
    發表于 06-05 17:20 ?0次下載