ARM巨集定義(轉自http://blog.sina.com.cn/s/blog_671dfeb101013n7s.html)

俺是阿木木發表於2020-11-17

巨集是一段獨立的程式程式碼,它是通過偽指令定義的,在程式中使用巨集指令即可呼叫巨集。當程式被彙編時,彙編程式將對每個呼叫進行展開,用巨集定義取代源程式中的巨集指令。

MACRO、MEND
語法格式:
MACRO
[$ label] macroname{ $ parameter1, $ parameter,…… }
指令序列
MEND
MACRO偽操作標識巨集定義的開始,MEND標識巨集定義的結束。用MACRO及MEND定義一段程式碼,稱為巨集定義體,這樣在程式中就可以通過巨集指令多次呼叫該程式碼段。
其中, $ label在巨集指令被展開時,label會被替換成相應的符號,通常是一個標號。在一個符號前使用 表 示 程 序 被 匯 編 時 將 使 用 相 應 的 值 來 替 代 表示程式被彙編時將使用相應的值來替代 使後的符號。
macroname為所定義的巨集的名稱。
p a r a m e t e r 為 巨集 指 令 的 參 數 。 當 巨集 指 令 被 展 開 時 將 被 替 換 成 相 應 的 值 , 類 似 於 函 數 中 的 形 式 參 數 , 可 以 在 巨集 定 義 時 為 參 數 指 定 相 應 的 默 認 值 。 巨集 指 令 的 使 用 方 式 和 功 能 與 子 程 序 有 些 相 似 , 子 程 序 可 以 提 供 模 塊 化 的 程 序 設 計 、 節 省 存 儲 空 間 並 提 高 運 行 速 度 。 但 在 使 用 子 程 序 結 構 時 需 要 保 護 現 場 , 從 而 增 加 了 系 統 的 開 銷 , 因 此 , 在 代 碼 較 短 且 需 要 傳 遞 的 參 數 較 多 時 , 可 以 使 用 巨集 匯 編 技 術 。 首 先 使 用 M A C R O 和 M E N D 等 偽 操 作 定 義 巨集 。 包 含 在 M A C R O 和 M E N D 之 間 的 代 碼 段 稱 為 巨集 定 義 體 , 在 M A C R O 偽 操 作 之 後 的 一 行 聲 明 巨集 的 原 型 ( 包 含 巨集 名 、 所 需 的 參 數 ) , 然 後 就 可 以 在 匯 編 程 序 中 通 過 巨集 名 來 調 用 它 。 在 源 程 序 被 匯 編 時 , 匯 編 器 將 巨集 調 用 展 開 , 用 巨集 定 義 體 代 替 源 程 序 中 的 巨集 定 義 的 名 稱 , 並 用 實 際 參 數 值 代 替 巨集 定 義 時 的 形 式 參 數 。 巨集 定 義 中 的 parameter為巨集指令的引數。當巨集指令被展開時將被替換成相應的值,類似於函式中的形式引數,可以在巨集定義時為引數指定相應的預設值。 巨集指令的使用方式和功能與子程式有些相似,子程式可以提供模組化的程式設計、節省儲存空間並提高執行速度。但在使用子程式結構時需要保護現場,從而增加了系統的開銷,因此,在程式碼較短且需要傳遞的引數較多時,可以使用巨集彙編技術。 首先使用MACRO和MEND等偽操作定義巨集。包含在 MACRO 和 MEND 之間的程式碼段稱為巨集定義體,在MACRO偽操作之後的一行宣告巨集的原型(包含巨集名、所需的引數),然後就可以在彙編程式中通過巨集名來呼叫它。在源程式被彙編時,彙編器將巨集呼叫展開,用巨集定義體代替源程式中的巨集定義的名稱,並用實際引數值代替巨集定義時的形式引數。 巨集定義中的 parameter巨集巨集巨集巨集使使使巨集使MACROMEND巨集MACROMEND巨集MACRO巨集巨集巨集調巨集調巨集巨集巨集巨集label是一個可選引數。當巨集定義體中用到多個標號時,可以使用類似 l a b e l . label. label.internallabel的標號命名規則使程式易讀。
MACRO 、 MEND 偽操作可以巢狀使用。
使用示例:
MACRO
$HandlerLabel HANDLER H a n d l e L a b e l ; 巨集 的 名 稱 為 H A N D L E R , 有 1 個 參 數 HandleLabel ;巨集的名稱為HANDLER,有1個引數 HandleLabel巨集HANDLER1HandleLabel

KaTeX parse error: Expected 'EOF', got '#' at position 24: …abel sub sp,sp,#̲4 ;decrement sp…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
;在程式中呼叫該巨集
HandlerFIQ HANDLER HandleFIQ ;通過巨集的名稱HANDLER呼叫巨集,其中巨集的標號為HandlerFIQ,引數為HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort

也許我們會問想格式中的[$ label]到底有什麼作用?

當巨集定義體內部跳轉時,這個引數會起到至關重要的作用。要想在巨集內部跳轉,就必須在巨集定義體內部有程式標號如(LOOP),如果不使用引數($ label),當在一個程式段內呼叫兩次巨集的時候,編譯器就會出現錯誤,因為當彙編時產生了兩個相同名字的程式標號。

例子:

巨集的定義體:

MACRO
$PM DELAY $CanShu
P M L D R R 7 , = PM LDR R7,= PMLDRR7,=CanShu ;
;LDR R7,[R7] ;此時引數是一個立即數 如果是變數的話 是會用到這一句
$PM.LOOP
SUBS R7,R7,#0X01
BNE $PM.LOOP

        MEND

在程式段中的使用:(使用兩次)

AA DELAY 0X000005F0

BB DELAY 0X00000FF0

此時呼叫多次,編譯器就不會出現問題,例子中的AA和BB僅僅是一個標號,使用者可以自行書寫,因為在巨集指令唄展開時,這個符號在彙編時將使用相應的值替代

0x00000FF0是一個引數在此處是一個立即數,使用者可自行使用為變數等

相關文章