汇编工程排版说明
1、汇编中的宏定义,大写且前缀加MAC,如下:
MAC_XXX_XX EQU 1
2、定义变量,前缀加VAR;局部变量小写,全局变量首字母大写
VAR_XXX DS 1
3、定义位变量(可作为标志位)
workflag DS 2
BF_XXX EQU (workflag+0).0
...
BF_XXX EQU (workflag+0).7
BF_XXX EQU (workflag+1).0
4、定义引脚
PIN_Led_Red EQU P0.0
5、定义跳转位置
JMP JMP_XXX ;跳转
JMP_XXX:
BTS0 XXX
6、定义函数
;---------------------------------------------------------------------------------------
; 函数功能:
; XXX
; 入口参数:
; 1. XXX 2.XXX ……
; 出口参数:
; 1. XXX 2.XXX ……
; 占用资源:
; 1. XXX 2.XXX ……
; 堆栈深度:
; SP_DEPTH = 1
;---------------------------------------------------------------------------------------
func_XXX:
XXX XXX
……
RET
程序状态寄存器 PFLAG 中常用标志 C、DC、Z
- C:进位标志。
1 = 加法运算后有进位、减法运算没有借位发生或移位后移出逻辑“1”或比较运算的结果 ≥ 0;
0 = 加法运算后没有进位、减法运算有借位发生或移位后移出逻辑“0”或比较运算的结果 < 0。 - DC:辅助进位标志。
1 = 加法运算时低四位有进位,或减法运算后没有向高四位借位;
0 = 加法运算时低四位没有进位,或减法运算后有向高四位借位。 - Z:零标志。
1 = 算术/逻辑/分支运算的结果为零;
0 = 算术/逻辑/分支运算的结果非零。
常用的判断指令 BTS0、BTS1
BTS0 M.b | 如果 M.b = 0,则跳过下一条指令 |
---|---|
BTS1 M.b | 如果 M.b = 1,则跳过下一条指令 |
用 XOR(异或)判断两变量是否相同
异或运算:相同为0,不同为1;
两变量相同,异或运算为0;两变量不同,异或运算为1;
进行异或运算后(也是逻辑运算),零标志(Z)状态会改变:
- Z:零标志。
1 = 逻辑运算的结果为零;
0 = 逻辑运算的结果非零。
B0MOV A,var1
XOR A,#AA ; "#AA"可以是宏定义或变量 (异或:两变量值相同为0(FZ==1),两变量值不同为1(FZ==0))
B0BTS0 FZ
JMP JMP_XXX
...
;------------------------------------------------------------------------------------------
B0MOV A,var2
XOR A,#BB ;
B0BTS1 FZ
JMP JMP_XXX
...
用SUB(减法)判断两变量大小
SUB A,M | A ← A – M,如果产生借位则 C=0,否则 C=1。 |
---|---|
SUB M,A | M ← A – M,如果产生借位则 C=0,否则 C=1。 |
;subtract word
SUBW MACRO m_minuend,m_subtrahend //m_minuend=m_minuend-m_subtrahend
MOV A,m_minuend
SUB A,m_subtrahend
MOV m_minuend,A // save low byte
MOV A,m_minuend+1
SBC A,m_subtrahend+1
MOV m_minuend+1,A // save high byte
ENDM
;------------------------------------------------------------------------------------------
AAA DS 2 ; 临时双字节寄存器AAA
BBB DS 2 ; 临时双字节寄存器BBB
;------------------------------------------------------------------------------------------
;双字节变量的比较
B0MOV A,var1 + 0 ; var1 + 0:表示字节1
B0MOV AAA + 0,A
B0MOV A,var1 + 1 ; var1 + 1:表示字节2
B0MOV AAA + 1,A
MOV A,#CON1$L ; #CON1$L 低字节
B0MOV BBB+0,A
MOV A,#CON1$M ; #CON1$M 中字节
B0MOV BBB + 1,A
SUBW AAA,BBB ; var1 -CON1(AAA >= BBB,FC为1)
B0BTS1 FC ; 也可以用 B0BTS0
JMP JMP_XXX ; var1 < CON1
... ; var1 > CON1
;------------------------------------------------------------------------------------------
;单字节变量的比较
B0MOV A,var1 ;
B0MOV AAA ,A
MOV A,#CON1 ;
B0MOV BBB,A
SUBW AAA,BBB ; var1 -CON1(AAA >= BBB,FC为1)
B0BTS1 FC ; 也可以用 B0BTS0
JMP JMP_XXX ; var1 < CON1
... ; var1 > CON1
用跳转表实现如C语言switch功能
B0MOV A, BUF0 ; “BUF0”从 0 至 4。
@JMP_A 5 ; 列表个数为 5。
JMP A0POINT ; ACC = 0,跳至 A0POINT。
JMP A1POINT ; ACC = 1,跳至 A1POINT。
JMP A2POINT ; ACC = 2,跳至 A2POINT。
JMP A3POINT ; ACC = 3,跳至 A3POINT。
JMP A4POINT ; ACC = 4,跳至 A4POINT。
扫描按键输入
按键连接同一个端口
key0、key1、key2、key3 分别连接 P1端口的P1.0、P1.1、P1.2、P1.3;
;最后 keycode 返回的是序号,而不是 TBL_KEY 表中的值
KEYIN:
MOV A,P1 ; (有按键按下,相应位为0)
XOR A,#0xFF ; 此处是为了避免不按键时与结束码相同,键码取反(即有按键按下,相应位为1)(XOR:相同为0,不同为1)
AND A,#0x0F ; 屏蔽非按键IO口
KEYIN1:
B0MOV R1,A ; A 保存了按键值,如果只有P1.0按下,则A值为0x01
MOV A,#0xFF
B0MOV R0,A ; R1 为按键状态,R0 为0xFF
KEYIN2:
B0MOV Y,#TBL_KEY$M
B0MOV Z,#TBL_KEY$L
INCMS R0 ; 第一遍R0 == 0 ;第二遍 R0 == 1;...
NOP
B0MOV A,R0 ; A 即 R0 的值;
B0ADD Z,A ; 第一遍 Z == #TBL_KEY$L;第二遍 Z 为 #TBL_KEY$L 的下一个地址;...(ADD,如果产生进位则 C = 1,否则 C = 0。 )
B0BTS1 FC ;
JMP FIND_KEYTBL
INCMS Y
NOP
FIND_KEYTBL:
MOVC ; 查表(执行完 MOVC 指令后,所查找数据低字节内容被存入 ACC 中,而数据高字节内容被存入 R 寄存器。)
CMPRS A,R1 ; A 存储的是 TBL_KEY 表中的值,R1 即按键状态
JMP KEYIN3 ; A != R1 ,
B0MOV A,R0 ; A == R1 , 将 R0 序号(0、1、2、3...)赋值给keycode,而不是将TBL_KEY 表中的值
B0MOV keycode,A
RET
KEYIN3:
CMPRS A,#0xFF ; 比较,如果相等则跳过下一条指令(0xFF是TBL_KEY表中结尾的值,所以前面值都不等,最后一个就一定等)
JMP KEYIN2 ; 没有查完 TBL_KEY 表,循环查找
B0MOV keycode,A ;
RET
TBL_KEY: ; 如key0(P1.0)按下,按键值为0x01,
DW 0x0000 ; ---------------> 无按键按下
DW 0x0001 ; ---------------> key0 按下
DW 0x0002 ; ---------------> key1 按下
DW 0x0004 ; ---------------> key2 按下
DW 0x0008 ; ---------------> key3 按下
DW 0x00FF ; ---------------> 无定义的按键值
按键连接不同端口
key0、key1、key2、key3 分别连接 P1端口的P5.4、P5.5、P1.2、P1.3;
KEYIN:
MOV A,P1
XOR A,#0xFF ; 此处是为了避免不按键时与结束码相同,键码取反
AND A,#(BIT2|BIT3) ; 屏蔽非按键IO口(读取P1^2,P1^3)
B0MOV R1,A
MOV A,P5
XOR A,#0xFF ; 此处是为了避免不按键时与结束码相同,键码取反
AND A,#(BIT4|BIT5) ; 屏蔽非按键IO口(读取P5^4,P5^5)
OR R1,A ; 综合P1 & P5两个IO口
KEYIN1:
MOV A,#0xFF
B0MOV R0,A
KEYIN2:
B0MOV Y,#TBL_KEY$M
B0MOV Z,#TBL_KEY$L
INCMS R0
NOP
B0MOV A,R0
B0ADD Z,A
B0BTS1 FC
JMP FIND_KEYTBL
INCMS Y
NOP
FIND_KEYTBL:
MOVC ;
CMPRS A,R1
JMP KEYIN3
B0MOV A,R0
B0MOV keycode,A
RET
KEYIN3:
CMPRS A,#0xFF
JMP KEYIN2
B0MOV keycode,A ;
RET
TBL_KEY: ; 如key0(P5.4)按下,按键值为0x10,
DW 0x0000 ; ---------------> 无按键按下
DW 0x0010 ; ---------------> key0 按下
DW 0x0020 ; ---------------> key1 按下
DW 0x0004 ; ---------------> key2 按下
DW 0x0008 ; ---------------> key3 按下
DW 0x0030 ; ---------------> key0&key1 同时按下
DW 0x00FF ; ---------------> 无定义的按键值