MACRO偽操作標識 宏定義的開始,MEND標識宏定義的結束。
用MACRO 及MEND定義一段代碼,稱為宏定義體,這樣在程序中就可以通過宏指令多次調(diào)用該代碼段
語法格式
MACRO
{$label} macroname {$parameter {,$parameter}...}
;code
...
;code
MEND
其中:
$labelz在宏指令被展開時,label可被替換成相應的符號,通常是一個標號。在一個符號前使用$標識程序被匯編時將使用相應的值來替代$后的符號
Macroname為所定義的宏的名稱
$parameter為宏指令的參數(shù)。當宏指令被展開時將被替換成相應的值,類似于函數(shù)中的形式參數(shù)??梢栽诤甓x時為參數(shù)指定相應的默認值。
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
;;在程序中調(diào)用
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
比如第一個為例說明 HandlerFIQ HANDLER HandleFIQ
;;程序被匯編后,宏展開的結果
HandlerFIQ
sub sp,sp,#4
stmfd sp!,{r0}
ldr r0,=HandleFIQ
ldr r0,[r0]
str r0,[sp,#4]
ldmfd sp!,{r0,pc}
下面一句一句分析一下,為了便于分析,假設sp =0x33ff8000,$HandleLabel =0x33ffff00,
[0x33ffff00]=0x10000000,r0 =0x56001234:
$HandlerLabel HANDLER $HandleLabel
宏的名字叫HANDLER ,有兩個參數(shù)
$HandlerLabel
定義一個標號
sub sp,sp,#4
把棧頂指針減4,留出一個字的空間(用于保存跳轉(zhuǎn)地址的值),sp=0x33ff7ffc
stmfd sp!,{r0}
首先把sp減4 (sp=0x33ff7ff8),然后把將要使用的r0寄存器入棧,此時[0x33ff7ff8]=0x56001234
ldr r0,=$HandleLabel
給寄存器r0賦值,r0=0x33ffff00
ldr r0,[r0]
給寄存器r0賦值,r0=0x10000000
str r0,[sp,#4]
;把寄存器r0保存到0x33ff7ffc (0x33ff7ff8+4),sp沒有改變sp=0x33ff7ff8,如果
str r0,[sp,#4]!sp 改變
此時
;[0x33ff7ffc] = 0x10000000
ldmfd sp!,{r0,pc}
把棧頂?shù)膬蓚€字彈出,分別保存到r0、pc,此時sp=0x33ff8000,r0=0x56001234,pc=0x10000000,通過比較不難發(fā)現(xiàn),sp和r0在執(zhí)行前后都沒有變化,程序就跳轉(zhuǎn)到0x10000000處執(zhí)行