在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

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

3天內不再提示

基于gcc將C語言變量與指令操作數相關聯

Linux閱碼場 ? 2018-01-16 14:55 ? 次閱讀

有時候我們希望在C/C++代碼中使用嵌入式匯編,因為C中沒有對應的函數或語法可用。比如我最近在ARM上寫FIR程序時,需要對最后的結果進行飽和處理,但gcc沒有提供ssat這樣的函數,于是不得不在C代碼中嵌入匯編指令。

1. 入門

在C中嵌入匯編的最大問題是如何將C語言變量與指令操作數相關聯。當然,gcc都幫我們想好了。下面是是一個簡單例子。

asm(“fsinx %1, %0”:”=f”(result):”f”(angle));

這里我們不需要關注fsinx指令是干啥的;只需要知道這條指令需要兩個浮點寄存器作為操作數。作為專職處理C語言的gcc編譯器,它是沒辦法知道fsinx這條匯編指令需要什么樣的操作數的,這就要求程序猿告知gcc相關信息,方法就是指令后面的”=f”和”f”,表示這是兩個浮點寄存器操作數。這被稱為操作數規則(constraint)。規則前面加上”=”表示這是一個輸出操作數,否則是輸入操作數。constraint后面括號內的是與該寄存器關聯的變量。這樣gcc就知道如何將這條嵌入式匯編語句轉成實際的匯編指令了:

fsinx:匯編指令名

%1, %0:匯編指令操作數

“=f”(result):操作數%0是一個浮點寄存器,與變量result關聯(對輸出操作數,“關聯”的意思就是說gcc執行完這條匯編指令后會把寄存器%0的內容送到變量result中)

“f”(angle):操作數%1是一個浮點寄存器,與變量angle關聯(對輸入操作數,“關聯”的意思是就是說gcc執行這條匯編指令前會先將變量angle的值讀取到寄存器%1中)

因此這條嵌入式匯編會轉換為至少三條匯編指令(非優化):

將angle變量的值加載到寄存器%1

fsinx匯編指令,源寄存器%1,目標寄存器%0

將寄存器%0的值存儲到變量result

當然,在高優化級別下上面的敘述可能不適用;比如源操作數可能本來就已經在某個浮點寄存器中了。

這里我們也看到constraint前加”=”符號的意義:gcc需要知道這個操作數是在執行嵌入匯編前從變量加載到寄存器,還是在執行后從寄存器存儲到變量中。

常用的constraints有以下幾個(更多細節參見gcc手冊):

m 內存操作數

r 寄存器操作數

i 立即數操作數(整數)

f 浮點寄存器操作數

F 立即數操作數(浮點)

從這個栗子也可以看出嵌入式匯編的基本格式:

asm(“匯編指令”:”=輸出操作數規則”(關聯變量):”輸入操作數規則”(關聯變量));

輸出操作數必須為左值;這個顯然。

2. 多個操作數,或沒有輸出操作數

如果某個指令有多個輸入或輸出操作數怎么辦?例如arm有很多指令是三操作數指令。這個時候用逗號分隔多個規則:

asm(“add %0, %1, %2”:”=r”(sum):”r”(a), “r”(b));

每條操作數規則按順序對應操作數%0, %1, %2。

對于沒有輸出操作數的情況,在匯編指令后就沒有輸出規則,于是就出現兩個連續冒號,后跟輸入規則。

3. 輸入-輸出(或讀-寫)操作數

有時候一個操作數既是輸入又是輸出,比如x86下的這條指令:

add %eax, %ebx

注意指令使用AT&T格式而不是Intel格式。寄存器ebx同時作為輸入操作數和輸出操作數。對這樣的操作數,在規則前使用”+”字符:

asm("add %1, %0" : "+r"(a) : "r"(b));

對應C語言語句a=a+b。

注意這樣的操作數不能使用”=”符號,因為gcc看到”=”符號會認為這是一個單輸出操作數,于是在將嵌入匯編轉換為真正匯編的時候就不會預先將變量a的值加載到寄存器%0中。

另一個辦法是將讀-寫操作數在邏輯上拆分為兩個操作數:

asm(“add %2, %0” : “=r”(a) : “0”(a), “r”(b));

對“邏輯”輸入操作數1指定數字規則”0”,表示這個邏輯操作數占用和操作數0一樣的“位置”(占用同一個寄存器)。這種方法的特點是可以將兩個“邏輯”操作數關聯到兩個不同的C語言變量上:

asm("add %2, %0" : "=r"(c) : "0"(a), "r"(b));

對應于C程序語句c=a+b。

數字規則僅能用于輸入操作數,且必須引用到輸出操作數。拿上例來說,數字規則”0”位于輸入規則段,且引用到輸出操作數0,該數字規則自身占用操作數計數1。

這里要注意,通過同名C語言變量是無法保證兩個操作數占用同一“位置”的。比如下面這樣的寫法是不行的:

(錯誤寫法)asm(“add %2, %0”:”=r”(a):”r”(a), “r”(b));

4. 指定寄存器

有時候我們需要在指令中使用指定的寄存器;典型的栗子是系統調用,必須將系統調用碼和參數放在指定寄存器中。為了達到這個目的,我們要在聲明變量時使用擴展語法:

register int a asm(“%eax”) = 1; // statement 1

register int b asm(“%ebx”) = 2; // statement 2

asm("add %1, %0" : "+r"(a) : "r"(b)); // statement 3

注意只有在執行匯編指令時能確定a在eax中,b在ebx中,其他時候a和b的存放位置是不可知的。

另外,在這么用的時候要注意,防止statement 2在執行時覆蓋了eax。例如statement 2改成下面這句:

register int b asm(“%ebx”) = func();

函數調用約定會將func()的返回值放在eax里,于是破壞了statement 1對a的賦值。這個時候可以先用一條語句將func返回值放在臨時變量里:

int t = func();

register int a asm(“%eax”) = 1; // statement 1

register int b asm(“%ebx”) = t; // statement 2

asm("add %1, %0" : "+r"(a) : "r"(b)); // statement 3

5. 隱式改變寄存器

有的匯編指令會隱含修改一些不在指令操作數中的寄存器,為了讓gcc知道這個情況,將隱式改變寄存器規則列在輸入規則之后。下面是VAX機上的栗子:

asm volatile(“movc3 %0,%1,%2”

: /* no outputs */

:”g”(from),”g”(to),”g”(count)

:”r0”,”r1”,”r2”,”r3”,”r4”,”r5”);

(movc3是一條字符塊移動(Move characters)指令)

這里要注意的是輸入/輸出規則中列出的寄存器不能和隱含改變規則中的寄存器有交叉。比如在上面的栗子里,規則“g”中就不能包含r0-r5。以指定寄存器語法聲明的變量,所占用的寄存器也不能和隱含改變規則有交叉。這個應該好理解:隱含改變規則是告訴gcc有額外的寄存器需要照顧,自然不能和輸入/輸出寄存器有交集。

另外,如果你在指令里顯式指定某個寄存器,那么這個寄存器也必須列在隱式改變規則之中(有點繞了哈)。上面我們說過gcc自身是不了解匯編指令的,所以你在指令中顯式指定的寄存器,對gcc來說是隱式的,因此必須包含在隱式規則之中。另外,指令中的顯式寄存器前需要一個額外的%,比如%%eax。

6. volatile

asm volatile通知gcc你的匯編指令有side effect,千萬不要給優化沒了,比如上面的栗子。

如果你的指令只是做些計算,那么不需要volatile,讓gcc可以優化它;除此以外,無腦給每個asm加上volatile或者是個好辦法。

基于gcc將C語言變量與指令操作數相關聯

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

    關注

    31

    文章

    5399

    瀏覽量

    122721
  • 內存
    +關注

    關注

    8

    文章

    3101

    瀏覽量

    74867
  • C語言
    +關注

    關注

    180

    文章

    7626

    瀏覽量

    139617
  • GCC
    GCC
    +關注

    關注

    0

    文章

    109

    瀏覽量

    25159

原文標題:byeyear: gcc內嵌匯編詳解

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 0人收藏

    評論

    相關推薦

    python的操作數據庫

    python操作數據庫
    發表于 05-20 12:11

    ARM指令集的格式與操作數符號簡析

    1)指令格式①一般格式{條件域}{執行時是否更新CPSR},,{第二個源操作數}其中內為不可省略,{}內為可省略。②指令中的條件域每條ARM指令包含4位的條件碼,位于
    發表于 01-07 07:29

    IBM-PC匯編語言指令

    IBM-PC匯編語言指令集 數據傳送指令集 MOV 功能: 把源操作數送給目的操作數 語法: MOV 目的
    發表于 12-25 10:08 ?1266次閱讀

    C#教程之Linq操作數組集合

    C#教程之Linq操作數組集合,很好的C#資料,快來學習吧。
    發表于 04-20 15:27 ?5次下載

    2按鍵加減操作數碼管顯示

    2按鍵加減操作數碼管顯示--C51單片機源碼,KEIL源文件,C語言編寫
    發表于 06-20 16:15 ?22次下載

    駕駛操作數據采集系統設計研究

    駕駛操作數據采集系統設計研究
    發表于 01-22 21:11 ?12次下載

    PLC的相關指令詳細介紹

    CMP指令有三個操作數:兩個源操作數[S1.]和[S2.],一個目標操作數[D.],該指令[S
    發表于 07-04 11:50 ?3720次閱讀
    PLC的<b class='flag-5'>相關</b><b class='flag-5'>指令</b>詳細介紹

    單片機尋找操作數存放單元地址的方法解析

    尋找操作數存放單元的地址的方式,共6種方式。 1.立即數尋址 所要找的操作數是一二進制數或十進制數,出現在指令中,用“#”作前綴 MOVA,#20H 2.寄存器尋址
    發表于 10-18 17:04 ?4229次閱讀
    單片機尋找<b class='flag-5'>操作數</b>存放單元地址的方法解析

    使用單片機實現兩按鍵加減操作數碼管顯示的C語言程序免費

    本文檔的主要內容詳細介紹的是使用單片機實現兩按鍵加減操作數碼管顯示的C語言程序免費。
    發表于 11-19 18:10 ?28次下載
    使用單片機實現兩按鍵加減<b class='flag-5'>操作數</b>碼管顯示的<b class='flag-5'>C</b><b class='flag-5'>語言</b>程序免費

    PLC編程中的操作數是什么

    操作數是指等待CPU處理的數據,也是指等待處理的數據所在的內存地址。操作數包括標識符和標識參數,標識符分為主標識符和輔助標識符。 (1)標識符(存儲操作數的內存區域):I、q、PI、PQ、m、t、
    發表于 12-20 10:13 ?8392次閱讀

    S7-1200比較操作-變量指令說明

    SCL指令:TypeOf(操作數),操作數是FC/FB的Input/Output/InOut/Temp中定義為Variant類型的參數,該語句輸出是數據類型,在程序中只能用在IF與CASE進行比較。
    的頭像 發表于 03-28 11:12 ?5151次閱讀

    簡單的gcc內嵌匯編例分析

    在內嵌匯編中,可以C語言表達式指定為匯編指令操作數,而且不用去管如何
    發表于 03-09 12:15 ?767次閱讀

    掃描操作數的信號上升沿

    使用“掃描操作數的信號上升沿”指令,可以確定所指定操作數)的信號狀態是否從“0”變為“1”。
    的頭像 發表于 06-27 09:39 ?2989次閱讀
    掃描<b class='flag-5'>操作數</b>的信號上升沿

    西門子博途:掃描操作數的信號下降沿

    使用“掃描操作數的信號下降沿”指令,可以確定所指定操作數)的信號狀態是否從“1”變為“0”。
    的頭像 發表于 07-17 10:51 ?3265次閱讀
    西門子博途:掃描<b class='flag-5'>操作數</b>的信號下降沿

    匯編指令是什么 計算機語言匯編指令簡介

    匯編指令簡介 匯編語言是計算機語言的一種,是一種低級語言。相比高級語言,匯編語言更接近底層硬件,
    的頭像 發表于 12-13 11:18 ?1551次閱讀
    匯編<b class='flag-5'>指令</b>是什么 計算機<b class='flag-5'>語言</b>匯編<b class='flag-5'>指令</b>簡介
    主站蜘蛛池模板: 国内露脸夫妇交换精品 | 色综合久久88 | 五月婷婷六月丁香在线 | 簧 色 成 人 | 一级一级特黄女人精品毛片 | 黄色3急| 在线免费观看91 | 亚洲欧美视频在线观看 | 骚淫| 日日夜夜操操 | 一级高清 | 国产精品久久久久久一级毛片 | 国产乱子伦一区二区三区 | 欧美性色综合网 | 在线色国产 | 欧美a一| 精品国产乱子伦一区 | 狠狠干2021| 国产视频二区 | 97人摸人人澡人人人超一碰 | 2021国产成人精品久久 | 天天视频黄 | 最近高清在线视频观看免费 | 狠狠色丁香久久婷婷综 | 无遮挡一级毛片视频 | 天天躁狠狠躁狠狠躁夜夜躁 | 欧美黄色免费网址 | 亚洲欧美v视色一区二区 | 日本国产黄色片 | 色网站在线播放 | 黄色大秀| 欧美二级黄色片 | 欧美精品啪啪 | 国产视频观看 | 国产三级日产三级韩国三级 | 免费播放欧美毛片欧美aaaaa | 天天插天天操天天干 | 人与牲动交bbbbxxxx | 中文字幕在线不卡 | 日本三级带日本三级带黄首页 | 亚洲青草视频 |

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品