新聞中心

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

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

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

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

        ②中斷使能

        下面的例子通過讀取程序狀態寄存器PSR并設置它的中斷使能位bit[7]來禁止/打開中斷。需要注意的是,該例只能運行在系統模式下,因為用戶模式是無權修改程序狀態寄存器的。

        __inlinevoidenable_IRQ(void)

        {

        inttmp;

        __asm

        {

        MRStmp,PSR

        BItmp,tmp,#0x80

        MSRCPSR_c,tmp

        }

        }

        __inlinevoiddisable_IRQ(void)

        {

        inttmp;

        __asm

        {

        MRStmp,CPSR

        ORRtmp,tmp,#0x80

        MSRCPSR_c,tmp

        }

        }

        intmain(void)

        {

        disable_IRQ();

        enable_IRQ();

        }

        ③分隔符的計算

        下面的例子計算兩個整數數組中分隔符“,”的個數。該例子顯示了如何在中訪問C或語言中的數據類型。該例中的函數mlal()被編譯器優化為一條SMLAL指令,可以使用-S–interleave編譯選項使編譯器輸出匯編結果。

        #includestdio.h>

        /*changewordorderifbig-endian*/

        #definelo64(a)(((unsigned*)a)[0]) /*longlong型的低32位*/

        #definehi64(a)(((int*)a)[1]) /*longlong型的高32位*/

        __inline__int64mlal(__int64sum,inta,intb)

        {

        #if!defined(__thumb)defined(__TARGET_FEATURE_MULTIPLY)

        __asm

        {

        SMLALlo64(sum),hi64(sum),a,b

        }

        #else

        sum+=(__int64)a*(__int64)b;

        #endif

        returnsum;

        }

        __int64dotprod(int*a,int*b,unsignedn)

        {

        __int64sum=0;

        do

        sum=mlal(sum,*a++,*b++);

        while(--n!=0);

        returnsum;

        }

        inta[10]={1,2,3,4,5,6,7,8,9,10};

        intb[10]={10,9,8,7,6,5,4,3,2,1};

        intmain(void)

        {

        printf(Dotproduct%lld(shouldbe%d)n,dotprod(a,b,10),220);

        return0;

        }

        2.中的限制

        可以在內聯匯編代碼中執行的操作有許多限制。這些限制提供安全的方法,并確保在匯編代碼中不違反C和代碼編譯中的假設。

        ①不能直接向程序計數器PC賦值。

        ②內聯匯編不支持標號變量。

        ③不能在程序中使用“.”或{PC}得到當前指令地址值。

        ④在16進制常量前加“0x”代替“”。

        ⑤建議不要對堆棧進行操作。

        ⑥編譯器可能會使用r12和r13寄存器存放編譯的中間結果,在計算表達式值時可能會將寄存器r0~r3、r12及r14用于子程序調用。另外在內聯匯編中設置程序狀態寄存器CPSR中的標志位NZCV時,要特別小心,內聯匯編中的設置很可能會和編譯器計算的表達式的結果沖突。

        ⑦用內聯匯編代碼更改處理器模式是可能的。然而,更改處理器模式會禁止使用C或操作數或禁止對已編譯C或C++代碼的調用,直到將處理器模式更改回原設置之后之前的函數庫才可正常使用。

        ⑧為Thumb狀態編譯C或C++時,內聯匯編程序不可用且不匯編Thumb指令。

        ⑨盡管可以使用通用協處理器指令指定VFP或FPA指令,但內聯匯編程序不為它們提供直接支持。

        不能用內聯匯編代碼更改VFP向量模式。內聯匯編可包含浮點表達式操作數,該操作數可使用編譯程序生成的VFP代碼求出操作數值。因此,僅由編譯程序修改VFP狀態很重要。

        ⑩內嵌匯編不支持的指令有BX、BLX、BXJ和BKPT指令。而LDM、STM、LDRD和STRD指令可能被等效為LDR或STR指令。

        3.內聯匯編中的虛擬寄存器

        內聯匯編程序提供對處理器物理寄存器的非直接訪問。如果在內聯匯編程序指令中將某個寄存器用作操作數,它就成為相同名稱的虛擬寄存器的引用,而不是對實際物理ARM寄存器的引用。例如內聯匯編指令中使用了寄存器r0,但對于C編譯器,指令中出現的r0只是一個變量,并非實際的物理寄存器r0,當程序運行時,可能是由物理寄存器r1來存放r0所代表的值。

        下面的例子顯示了編譯器如何對內聯匯編指令的寄存器進行分配。

        程序的源代碼如下。

        #includestdio.h>

        voidtest_inline_register(void)

        {

        inti;

        intr5,r6,r7;

        __asm

        {

        MOVi,#0

        loop:

        MOVr5,#0

        MOVr6,#0

        MOVr7,#0

        ADDi,i,#1

        CMPi,#3

        BNEloop

        }

        }

        intmain(void)

        {

        test_inline_register();

        printf(testinlineregistern);

        return0;

        }

        由C編譯器編譯出的匯編碼如下所示。

        test_inline_register:

        0000807CE3A00000MOVr0,#0

        >>>TEST_INLINE_REGISTER#12loop:

        00008080E1A00000NOP

        >>>TEST_INLINE_REGISTER#13MOVr5,#0

        00008084E3A01000MOVr1,#0

        >>>TEST_INLINE_REGISTER#14MOVr6,#0

        00008088E3A02000MOVr2,#0

        >>>TEST_INLINE_REGISTER#15MOVr7,#0

        0000808CE3A03000MOVr3,#0

        >>>TEST_INLINE_REGISTER#16ADDi,i,#1

        00008090E2800001ADDr0,r0,#1

        >>>TEST_INLINE_REGISTER#17CMPi,#3

        00008094E3500003CMPr0,#3

        000080980A000000BEQ0x80a0TEST_INLINE_REGISTER#21>

        >>>TEST_INLINE_REGISTER#18BNEloop

        0000809CEAFFFFF8B0x8084TEST_INLINE_REGISTER#13>

        >>>TEST_INLINE_REGISTER#21}

        000080A0E12FFF1EBXr14

        >>>TEST_INLINE_REGISTER#25{

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


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




        評論


        相關推薦

        技術專區

        主站蜘蛛池模板: 南川市| 宁国市| 海盐县| 金阳县| 饶阳县| 信宜市| 广河县| 宿迁市| 隆林| 永丰县| 聂拉木县| 七台河市| 红原县| 明溪县| 壶关县| 定州市| 韶关市| 新乡县| 如东县| 武强县| 民和| 安宁市| 红河县| 类乌齐县| 盐亭县| 增城市| 霍州市| 改则县| 奉节县| 牙克石市| 麻江县| 岱山县| 泾川县| 马尔康县| 桦南县| 夏邑县| 尖扎县| 和平区| 霍山县| 广宁县| 县级市|
        <ul id="202ag"></ul>