新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 混合使用C、C++和匯編語之:內聯匯編和嵌入型匯編的使用

        混合使用C、C++和匯編語之:內聯匯編和嵌入型匯編的使用

        作者: 時間:2013-09-30 來源:網絡 收藏

        本文引用地址:http://www.104case.com/article/257034.htm

        3.嵌入式匯編程序表達式和++表達式之間的差異

        嵌入式匯編表達式和表達式之間存在以下差異。

        ①匯編程序表達式總是無符號的。相同的表達式在匯編程序和C或中有不同值。例如:

        MOVr0,#(-33554432/2)//結果為0x7f000000

        MOVr0,#__cpp(-33554432/2)//結果為0xff000000

        ②以0開頭的匯編程序編碼仍是十進制的。例如:

        MOVr0,#0700//十進制700

        MOVr0,#__cpp(0700)//八進制0700等于十進制448

        ③匯編程序運算符優先順序與C和不同。例如:

        MOVr0,#(0x23:AND:0xf+1)//((0x230xf)+1)=>4

        MOVr0,#__cpp(0x230xf+1)//(0x23(0xf+1))=>0

        ④匯編程序字符串不是以空字符為終止標志的:

        DCBnotrailingnull//16bytes

        DCB__cpp(Ihaveatrailingnull!!)//25bytes

        注意

        在_cpp標識符作用范圍之內使用C或C++語法規則。

        4.嵌入式匯編函數的生成

        由關鍵字__asm聲明的嵌入式匯編程序,在編譯時將作為整個文件體傳遞給匯編器。傳遞過程中,__asm函數的順序保持不變(用模板實例生成的函數除外)。正是由于嵌入式匯編的這個特性,使得由一個__asm標識的嵌入式匯編程序調用在同一文件中的另一個嵌入式匯編程序是可以實現的。

        當使用編譯器armcc時,局部鏈接器(PartialLink)將匯編程序產生的目標文件與編譯C程序的目標文件相結合,產生單個目標文件。

        編譯程序為每個__asm函數生成AREA命令。例如,以下__asm函數:

        #includecstddef>

        structX{intx,y;voidaddto_y(int);};

        __asmvoidX::addto_y(int){

        LDRr2,[r0,#__cpp(offsetof(X,y))]

        ADDr1,r2,r1

        STRr1,[r0,#__cpp(offsetof(X,y))]

        BXlr

        }

        對于此函數,編譯程序生成:

        AREA||.emb_text||,CODE,READONLY

        EXPORT|_ZN1X7addto_yEi|

        #linenumfile

        |_ZN1X7addto_yEi|PROC

        LDRr2,[r0,#4]

        ADDr1,r2,r1

        STRr1,[r0,#4]

        BXlr

        ENDP

        END

        由上面的例子可以看出,對于變量offsetof的使用必須加__cpp()標識符才能引用,因為該變量是在cstddef頭文件中定義的。

        由__asm聲明的常規函數被放在名為.emb_text的段(Section)中。這一點也是嵌入式匯編和最大的不同。相反,隱式實例模板函數(ImplicitlyInstantiatedTemplateFunction)和函數放在與函數名同名的區域(Area)內,并為該區域增加公共屬性。這就確保了這類函數的特殊語義得以保持。

        由于內聯和模板函數的區域的特殊命名,所以這些函數不按照文件中定義的順序排列,而是任意排序。因此,不能以__asm函數在原文件中的排列順序,來判斷它們的執行順序,也就是說,即使兩個連續排列的__asm函數,也不一定能順序執行。

        5.關鍵字__cpp

        可用__cpp關鍵字從匯編代碼中訪問C或C++的編譯時常量表達式,其中包括含有外部鏈接的數據或函數地址。標識符__cpp內的表達式必須是適合用作C++靜態初始化的常量表達式(請參閱ISO/IEC14882:1998中的3.6.2非本地對象初始化一節和本書的常量表達式一節)。

        編譯時,編譯器將使用__cpp(expr)的地方用匯編程序可以使用的常量所取代。例如:

        LDRr0,=__cpp(some_variable)

        LDRr1,=__cpp(some_function)

        BL__cpp(some_function)

        MOVr0,#__cpp(some_constant_expr)

        __cpp表達式中的名稱可在__asm函數的C++上下文中查閱。__cpp表達式結果中的任何名稱按照要求被損毀并自動為其生成IMPORT語句。

        6.手動重復解決方案

        可以在嵌入式匯編中使用C++轉換為非虛擬函數調用解決重復。例如:

        voidg(int);

        voidg(long);

        structT{

        intmf(int);

        intmf(int,int);

        };

        __asmvoidf(T*,int,int){

        BL__cpp(static_castint(T::*)(int,int)>(T::mf))//callsT::mf(int,int)

        BL__cpp(static_castvoid(*)(int)>(g))//callsg(int)

        MOVpc,lr

        }

        c語言相關文章:c語言教程


        c++相關文章:c++教程




        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 博客| 鄂伦春自治旗| 寿宁县| 曲阳县| 唐海县| 保定市| 博乐市| 东明县| 准格尔旗| 西和县| 阿拉善左旗| 杂多县| 石首市| 白朗县| 南京市| 新建县| 阳新县| 华阴市| 屏东市| 磐石市| 普兰店市| 浦东新区| 福建省| 九台市| 加查县| 灵川县| 穆棱市| 紫云| 涪陵区| 武夷山市| 南皮县| 广河县| 峡江县| 若羌县| 绵竹市| 五峰| 徐州市| 绥宁县| 微博| 宜阳县| 安龙县|