單片機開發或多或少都會接觸一些匯編代碼,今天就來說說關于匯編在C中的定義和調用,以及舉例說明嵌套匯編代碼。
概 述
有認真研究,或者說細心一點的讀者應該都知道:C中定義匯編代碼與編譯器有關。 ? 比如,你在core_cm4.h文件會看到如下的代碼:
#if ? defined ( __CC_ARM ) ?#define __ASM ? ? ? ? ? ?__asm ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*!< asm keyword for ARM Compiler ? ? ? ? ? */ ?#define __INLINE ? ? ? ? __inline ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*!< inline keyword for ARM Compiler ? ? ? */ ?#define __STATIC_INLINE ?static __inline
?
#elif defined ( __GNUC__ ) ?#define __ASM ? ? ? ? ? ?__asm ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ?/*!< asm keyword for GNU Compiler ? ?
? ? ?*/ ?#define __INLINE ? ? ? ? inline ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? /*!< inline keyword for GNU Compiler ? ?
? */ ?#define __STATIC_INLINE ?static inline
#elif defined ( __ICCARM__ ) ?#define __ASM ? ? ? ? ? ?__asm ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ?/*!< asm keyword for IAR Compiler ? ? ?
? ?*/ ?#define __INLINE ? ? ? ? inline ? ? ? ? ?
?/*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ ?#define __STATIC_INLINE ?static inline
#elif defined ( __TMS470__ ) ?#define __ASM ? ? ?
? ? ?__asm ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ?/*!< asm keyword for TI CCS Compiler ? ?
? */ ?#define __STATIC_INLINE ?static inline
#elif defined ( __TASKING__ ) ?#define __ASM ? ?
? ? ? ?__asm ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?/*!< asm keyword for TASKING Compiler ?
? ?*/ ?#define __INLINE ? ? ? ? inline ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? /*!< inline keyword for TASKING Compiler ? */ ?#define __STATIC_INLINE ?static inline
#elif defined ( __CSMC__ ) ?#define __packed ?#define __ASM ? ? ? ? ? ?_asm ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?/*!< asm keyword for COSMIC Compiler ? ? ?*/ ?#define __INLINE ? ? ? ? inline ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?/*use -pc99 on compile line !< inline keyword for COSMIC Compiler ?
*/??#define __STATIC_INLINE??static inline#endif
如果你寫過Keil C51,你還會發現有如下(通過預處理)嵌套匯編:
#pragma asm
; Assembler Code Here
#pragma endasm
所以,你會發現,不同的編譯器,匯編代碼還是有差異。當然,這里主要是說C中嵌套匯編與編譯器有關。
C中嵌套匯編代碼
常見的兩種定義: ? 在C函數中定義一段匯編代碼 ? 在C文件中定義一個匯編函數 ? 當然,兩個意思差不多,都是在C中嵌套匯編。 ? 上面說了C中定義匯編代碼與編譯器有關,換句話說:不同編譯器解析匯編代碼的方式不同。 ? 這里還是拿core_cm3.c來舉例說明,定義一個__get_PSP函數。 ? 在Keil MDK中定義:
__ASM uint32_t __get_PSP(void){ ?mrs r0, psp ?bx lr}在IAR EWARM中定義: ?
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 ?{ ? ?/* Set BASEPRI to the max syscall priority to effect a critical section. */ ? ?msr basepri, ulNewBASEPRI ? ?dsb ? ?isb ?}}
2、FreeRTOS中port.c文件下源代碼:
__asm void xPortPendSVHandler( void ){ ?extern uxCriticalNesting; ?extern pxCurrentTCB; ?extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp ?isb
ldr ?r3, =pxCurrentTCB ? ?/* Get the location of the current TCB. */ ?ldr ?r2, [r3]
stmdb r0!, {r4-r11} ? ? ?/* Save the remaining registers. */ ?str r0, [r2] ? ? ? ?/* Save the new top of stack into the first member of the TCB. */
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] ? ? ? ?/* The first item in pxCurrentTCB is the task top of stack. */ ?ldmia r0!, {r4-r11} ? ? ?/* Pop the registers and the critical nesting count. */ ?msr psp, r0 ?isb ?bx r14 ?nop} 3、內核復位
這是分享過的一篇文章《一文弄懂STM32復位來源,以及系統與內核復位的區別》中的代碼:
__asm void NVIC_CoreReset_a(void){ ?LDR R0, =0xE000ED0C ?LDR R1, =0x05FA0001 ?STR R1, [R0]deadloop_Core ?B deadloop_Core}
以上這些常見例子,可能還沒有說透,但相信只要認真理解了都能明白。?
?
?
評論
查看更多