用!宏!這部分內容可能需要新版的編譯器,內容可有可無,也偏簡單
眾所周知,匯編是一個底層語言,但有時候會遇到很多很牛馬的情況,所以有了宏,宏簡單來說就是在代碼交給編譯器前進行一系列操作,比如關鍵字替換,復制粘貼之類的
首當其沖就是常量
比如這里有一個硬件,在每次開頭都要傳入一個特殊代碼,比如說是15吧,你不可能每次都手打
哦,你手打了,那邊剛傳來消息,那個芯片不用了,所以啟動代碼改成1了……
所以我們需要一個標記,本質來說,就是用EQU后面的替換點EQU前面的(實際比這個情況復雜,只能暫且這么理解)
好了,我們每次發送的時候只需要這樣就行了
- MOV R7,#CMD_START
- CALL SENT
復制代碼 很簡單,對吧,我們該應付下一個牛馬活計了
比如有一個東西,需要進行固定的序列來運行,假如是發送命令函數沒法用,手寫又犯惡心,所以我們干脆定義一段宏
- <div>宏名字 MARCO 變量</div><div>宏內容</div><div>ENDM</div>
復制代碼 在這個例子里面,我們就這樣寫- SENT_CMD MARCO K
- MOV R7,#K
- CALL SENT
- ENDM
復制代碼 如果需要發送一個命令,我們只需要
需要注意的是,變量是會原原本本替換的,也就是說,如果你在變量(SENT_CMD)后面填abcd,那么#K編譯時會被替換為#abcd
至于其他的內容比如內部標簽之類的,我覺得這個和函數有點沖突了,如果你執意要看,可以翻手冊
最后再講一些簡單的宏
有一個程序中間要插入100個NOP
REPT 次數
內容
ENDM
就像這樣
編譯器就把這活干了,這個地方會編譯100個nop
老板又提出了新的要求,要你把R1,R3,R5入棧,我們嘗試用IRP解決
IRP 枚舉名,<枚舉內容>
內容
ENDM
就像這樣
- IRP name,<1,3,5>
- PUSH R&name
- ENDM
復制代碼 它編譯出來是這樣的
對于字符,專門有一個方法,IRPC,我直接粘貼手冊給的程序
IRPC sendchar, TEST
MOV R0, #'sendchar'
CALL outchar
ENDM
編譯成
MOV R0, #'T'
CALL outchar
MOV R0, #'E'
CALL outchar
MOV R0, #'S'
CALL outchar
MOV R0, #'T'
CALL outchar
注: 188610329對上一次的內容進行勘誤,回看手冊發現確實不太一樣,具體按照大佬所給的表為準,或者看手冊User's Guides for Keil C51 Development Tools
另外,我對大佬所說不使用EQU定義引腳的說法不敢茍同,在這一章的內容可以明確知道EQU使用的是宏,是對代碼的前處理,而對于引腳寄存器的DATA定義早在STARTUP.A51就已經完成,甚至public了,在一般情況下已經具有所謂的“獨占性”,最重要的是,EQU最簡單的一點就是用就完了,你不需要考慮別的,在使用定義標記與宏最終效果一樣的情況下,肯定是選擇最簡單最靈活的那個
data的好處是可以public一個變量,但我在有一堆寄存器和形參,以及可以寫C的情況下似乎找不出使用這個的理由……本身就是寫底層的代碼,在有編譯器高效優化的前提下硬手寫匯編運算和編譯器比水平實在不是什么好行為……另外,匯編的內容基本就這些了
|