用!宏!这部分内容可能需要新版的编译器,内容可有可无,也偏简单
众所周知,汇编是一个底层语言,但有时候会遇到很多很牛马的情况,所以有了宏,宏简单来说就是在代码交给编译器前进行一系列操作,比如关键字替换,复制粘贴之类的
首当其冲就是常量
比如这里有一个硬件,在每次开头都要传入一个特殊代码,比如说是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的情况下似乎找不出使用这个的理由……本身就是写底层的代码,在有编译器高效优化的前提下硬手写汇编运算和编译器比水平实在不是什么好行为……另外,汇编的内容基本就这些了
|