在C中嵌套彙編代碼難嗎?

2020-12-11 電子工程專輯

做底層軟體開發的,或多或少都會接觸一些彙編代碼,今天就來說說關於彙編在C中的定義和調用,以及舉例說明嵌套彙編代碼。
有認真研究,或者說細心一點的讀者應該都知道:C中定義彙編代碼與編譯器有關
比如:你在core_cm4.h文件會看到如下的代碼:
#if   defined ( __CC_ARM )  #define __ASM            __asm                                        #define __INLINE         __inline                                     #define __STATIC_INLINE  static __inline
#elif defined ( __GNUC__ ) #define __ASM __asm #define __INLINE inline #define __STATIC_INLINE static inline
#elif defined ( __ICCARM__ ) #define __ASM __asm #define __INLINE inline #define __STATIC_INLINE static inline
#elif defined ( __TMS470__ ) #define __ASM __asm #define __STATIC_INLINE static inline
#elif defined ( __TASKING__ ) #define __ASM __asm #define __INLINE inline #define __STATIC_INLINE static inline
#elif defined ( __CSMC__ ) #define __packed #define __ASM _asm #define __INLINE inline   #define __STATIC_INLINE  static inline#endif

如果你寫過Keil C51,你還會發現有如下(通過預處理)嵌套彙編:
#pragma asm
; Assembler Code Here
#pragma endasm

所以,你會發現,不同的編譯器,彙編代碼還是有差異。當然,這裡主要是說C中嵌套彙編與編譯器有關

1.在C函數中定義一段彙編代碼;

2.在C文件中定義一個彙編函數;


上面說了C中定義彙編代碼與編譯器有關,換句話說:不同編譯器解析彙編代碼的方式不同。
這裡還是拿core_cm3.c來舉例說明,定義一個__get_PSP函數。
__ASM uint32_t __get_PSP(void){  mrs r0, psp  bx lr}

uint32_t __get_PSP(void){  __ASM("mrs r0, psp");  __ASM("bx lr");}

__asm(__ASM)關鍵字用於調用內聯彙編程序,並且可在 C 或 C++ 語句合法時出現。
1.FreeRTOS中portmacro.h文件下原始碼:
static portFORCE_INLINE void vPortRaiseBASEPRI( void ){uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm { msr basepri, ulNewBASEPRI dsb isb }}

__asm void xPortPendSVHandler( void ){  extern uxCriticalNesting;  extern pxCurrentTCB;  extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp isb
ldr r3, =pxCurrentTCB ldr r2, [r3]
stmdb r0!, {r4-r11} str r0, [r2]
stmdb sp!, {r3, r14} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r0 dsb isb bl vTaskSwitchContext mov r0, #0 msr basepri, r0 ldmia sp!, {r3, r14}
ldr r1, [r3] ldr r0, [r1] ldmia r0!, {r4-r11} msr psp, r0 isb bx r14 nop}

這是之前分享過的一篇文章《STM32復位來源》中的代碼:
__asm void NVIC_CoreReset_a(void){  LDR R0, =0xE000ED0C  LDR R1, =0x05FA0001  STR R1, [R0]deadloop_Core  B deadloop_Core}

舉了這些常見例子,沒有說透,但相信只要認真理解了都能明白。
‧  END  

關注微信公眾號『strongerHuang』,後臺回復「1024」,查看更多精彩內容。


長按識別圖中二維碼關注

相關焦點

  • ARM中ADS環境下C語言和彙編語言混合編程及示例
    稍大規模的嵌入式程序設計中,大部分的代碼都是用C來編寫的,主要是因為C語言具有較強的結構性,便於人的理解,並且具有大量的庫支持。但對於一寫硬體上的操作,很多地方還是要用到彙編語言,例如硬體系統的初始化中的CPU 狀態的設定,中斷的使能,主頻的設定,RAM控制參數等。
  • arm:c語言和彙編混合編程
    1.C和彙編可相互調用,彙編子函數格式參考彙編:普通的函數調用的彙編代碼解析http://www.cnblogs.com/mylinux/p/4139972.html本文引用地址:http://www.eepw.com.cn/article/201611/317685.htm  本文演示了 : 彙編嵌入到c語言;
  • DSP編程技巧之24---C/C++與彙編語言的交互之-(2)從C/C++代碼調用...
    本文引用地址:http://www.eepw.com.cn/article/264157.htm  1.從C/C++中調用彙編代碼中的函數  如果一個在彙編代碼中定義的函數需要在C/C++中被調用,那麼這個彙編函數相對於C/C++代碼來說,相當於一個外部的函數,所以需要使用extern "C"關鍵字進行特別聲明
  • 混合使用C、C++和彙編語之:內聯彙編和嵌入型彙編的使用
    使用它可以在C/C++程序中實現C/C++語言不能完成的一些工作。例如,在下面幾種情況中必須使用內聯彙編或嵌入型彙編。·程序中使用飽和算術運算(Saturatingarithmetic),如SSAT16和USAT16指令。·程序中需要對協處理器進行操作。
  • Keil中C語言與彙編語言混合編程需要注意的幾個地方
    1、C語言中加入彙編語言模塊的方法:例子:void func(){C語言代碼……#pragma asmMOV R6,#23DELAY2: MOV R7,#191DELAY1: DJNZ R7,DELAY1DJNZ R6,DELAY2RET
  • 哪幾種情況中必須使用內聯彙編或嵌入型彙編?
    ARM系列文章,請點擊以下匯總連結:《從0學arm合集》一、gcc 內聯彙編內聯彙編即在C中直接使用彙編語句進行編程,使程序可以在C程序中實現C語言不能完成的一些工作,例如,在下面幾種情況中必須使用內聯彙編或嵌入型彙編。
  • 你知道C語言中函數調用和嵌套嗎?函數必學模塊,你不得不知!
    示例代碼如下所示: 3、將函數作為實參調用 將函數作為另一個函數的實參時,要求該函數有返回值。示例代碼如下所示: 在上面的語句中,將函數max()的返回值作為printf()函數的實參來使用。
  • 反彙編代碼還原之除數為非2的冪
    那麼可以得出以下公式:最終簡化為就是(a * c) >> n,而反過頭來看我們的彙編代碼:.text:00401061 mov eax, 38E38E39h.text:00401067 imul ecx.text:00401069
  • 為何C語言函數調用要堆棧,而彙編卻不需要?
    而在Uboot的start.S彙編代碼中,關於系統初始化,也看到有堆棧指針初始化這個動作。但是,從來只是看到有人說系統初始化要初始化堆棧,即正確給堆棧指針sp賦值,但是卻從來沒有看到有人解釋,為何要初始化堆棧。
  • 【本質】你知道C語言編譯的過程嗎?
    那麼,你知道從原始碼到可執行文件經歷了哪些過程嗎。僅僅是編譯?下面以windows環境下的test.c為例,test.c裡的代碼為:上述命令中-E是讓編譯器在預處理之後就退出,不進行後續編譯過程;-o是指定輸出文件名。
  • 從AT&T彙編語言的HelloWorld說起
    從這裡可以看出上面彙編的代碼就是輸出了"Hello World"如果你在輸出結束後使用echo  $?,你會發現他的退出值為0(正常退出)如果你使用gdb,符號信息無法加載,這時你可以在as編譯的時候加上-g 或者 -gstabs,這樣你就可以調試彙編代碼了代碼解析1.以#為開關的行為彙編代碼的注釋2..section定義一個節或者叫段,如.rodata, .data, .text分別表示只讀數據段、數據段、代碼段
  • ARM彙編特殊符號 彙編符號引用
    %----SPACE----分配一塊內存,並用「0」初始化----DataStruc SPACE 280;分配280位元組內存並初始化[|] ----IF ELSE ENDIF----條件編譯,有選擇的確定需要編譯的代碼IF,ELSE,ENDIF,可以嵌套使用----IF 邏輯表達式指令或偽指令ELSE指令或偽指令
  • C語言與彙編語言的區別
    如果你問一個程式設計師這樣的問題,他也許會這麼回答你:「C語言可讀性好,代碼便於維護,便於開發;彙編語言編寫的程序不容易看懂,可維護性不好,但是執行效率高。」這樣回答是沒有錯的,但只是一個概括,不夠深入。比方說,彙編語言為什麼執行效率比C語言高呢?C語言的可讀性又好在哪裡呢?彙編語言不同樣可以用註解來提高可讀性嗎?等等這些的問題。
  • 有關arm彙編中的align
    經常會看到arm-linux彙編中有如下的指令:.align n它的含義就是使得下面的代碼按一定規則對齊,.align n 指令的對齊值有兩種方案,n 或 2^n ,各種平臺最初的彙編器一般都不是gas,採取方案1或2的都很多,gas的目標是取代原來的彙編器,必然要保持和原來彙編器的兼容,因此在gas中如何解釋 .align指令會顯得有些混亂,原因在於保持兼容。
  • 彙編技術內幕(2)
    --------------------+----> 低地址frame of C 圖 1-1 再分析test1反彙編結果中剩餘部分語句的含義 注意到優化後的代碼中,eax返回值的設置由 movl $0,%eax 變為 xorl %eax,%eax ,這是因為IA32指令中,xorl比movl有更高的運行速度。
  • const 並不能加快 C 代碼的運行速度?
    讓我們來看看GCC經過優化後生成的彙編代碼:$ gcc -S -Wall -O3 test.c$ view test.s如下是byArg()完整的彙編代碼:byArg:.LFB23: .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movl
  • @程式設計師,快來速取硬核的彙編語言知識大全!
    通過編譯器輸出彙編語言的原始碼上面提到本地代碼可以經過反彙編轉換成為彙編代碼,但是只有這一種轉換方式嗎?顯然不是,C 語言編寫的原始碼也能夠通過編譯器編譯稱為彙編代碼,下面就來嘗試一下。bcc32-c-SSample4.cbcc32 是啟動 Borland C++ 的命令,-c 的選項是指僅進行編譯而不進行連結,-S 選項被用來指定生成彙編語言的原始碼。作為編譯的結果,當前目錄下會生成一個名為Sample4.asm 的彙編語言原始碼。
  • DUP的嵌套
    這種格式,彙編不能通過,如圖1所示。圖1有兩種解決辦法,一種是將?替換成0,賦予它一個初值,即寫成:A3 DB 3 DUP(0)。另一種辦法是給?加單引號,即寫成:A3 DB 3 DUP(『?』) ,從圖2可看出A3變量定義的3個字節均為22H。
  • ds18b20彙編程序與c程序
    ds18b20 c程序本文引用地址:http://www.eepw.com.cn/article/172838.htm//DS1820 C51 子程序//這裡以11.0592M晶體為例,不同的晶體速度可能需要調整延時的時間//
  • 零基礎學會VBA循環嵌套,讓複雜化工作變為可能,簡直不要太簡單
    你殊不知在我們日常的編寫過程中,經常會遇到將一個循環放置在另外一循環中的,通俗意義上說的是循環嵌套的使用。VBA允許將不同類型的循環(For和Do循環)「嵌套」在同一個過程裡。因此當我們編寫循環嵌套時,請確保每個內部的循環在外部循環裡面已經完成。另外,每個循環都必須有其自己獨特的計數器變量(如i,j)。如果使用循環嵌套,那麼你可以更有效地,更加高效的執行特定的任務。