汇编入门(二)
RLC,RRC A 带进位累加器循环左移/右移
JC,JNC rel 进位为1/0时转移
JB,JNB bit,rel 某一位为1/0时转移
INC,DEC A 寄存器加1/减1
DJNZ Rn rel 寄存器减一,不为0则转移(循环转移指令)
1.输出0-1转变的次数到累加器A中
RLC:
JNB:
;0-1转变的次数 累加器A中
ORG 0000H
MOV A,#10101011B
MOV R1,#0
MOV R2,#7
L0: RLC A ;带进位累加器循环左移,A最高位的值放在C里
JC L1 ;如果进位位为1 则转移到L1; JC进位为1转移,JNC进位为0转移
JNB ACC.7,L1 ;判断ACC的第7位是否为0 若是则转移到L1;
INC R1 ;R1加1
L1: DJNZ R2,L0 ;R2减1,若不为0 则转移到L0
MOV A,R1
END
2.已知s=’…’ 的字符串,以0结束。问a=’ ',是否在s中
ORG 0000H ;伪指令,定义下面的指令所在地址,此句为主程序开始地址
LJMP MAIN ;无条件转移到MAIN
MAIN:
MOV DPTR,#S
MOV B,#m
L1:
CLR A
MOVC A,@A+DPTR ;将A中的值,加上DPTR里的值,访问程序段中这个地址的值,取出来送给A。
INC DPTR ;自加1,准备读取下一个字符
JZ LEND ;这是条件跳转语句,意思是,当累加器A中的值为0时,即到达字符串末尾,跳转到LEND语句行执行程序
CJNE A,B,L1 ;判断A和B是否相等,相等则顺序执行,不相等则执行L1
MOV A,#'Y'
SJMP LEND2
LEND:
MOV A,#'N'
SJMP LEND2
LEND2:
RET
s: DB'HELLO' ;DB定义数据表
m EQU 'L' ;EQU给一个表达式或一个字符串起名
END ;程序结束
ORG 0000H ;伪指令,定义下面的指令所在地址,此句为主程序的开始地址
LJMP MAIN ;无条件转移到MAIN
MAIN: ;主程序
//赋值
HEX0 DATA 83H ;存16进制高八位,这里对应DPTR,便于调试
HEX1 DATA 82H ;存16进制低八位
DEC0 DATA 05H ;存BCD高高八位
DEC1 DATA 06H ;存BCD高八位
DEC2 DATA 07H ;存BCD低八位
MOV HEX0,#0
MOV HEX1,#0
MOV DEC0,#07H
MOV DEC1,#55H
MOV DEC2,#35H
//十进制数不能大于65535,MUL大于65535会溢出,故大于65535直接无效,OV=1
//高高位大于7直接无效
MOV A,#0F0H ;高位不为0直接跳转
ANL A,DEC0
CJNE A,#0,FLOWOUT
//低位大于7也直接跳转
MOV A,#0FH
ANL A,DEC0
ADD A,#9 ;7+9=16会进一位
MOV R4,#0F0H
MOV 71H,R4
ANL A,R4
MOV 70H,A
CJNE A,#0,FLOWOUT
//将DEC0,1,2中分别转换为十六进制,5个数放入以60H开始的地址中
MOV R0,#05H
MOV R1,#60H
MOV R3,#3
L0:
MOV A,@R0
ANL A,#0F0H
SWAP A
MOV @R1,A
INC R1
MOV A,@R0
ANL A,#0FH
MOV @R1,A
INC R1
INC R0
DJNZ R3,L0
//开始对5个数循环处理
MOV R1,#60H ;下一个储存单元从61H开始
MOV R2,#5;循环5次
L1:
//由于数在寄存器中显示出的就是其十六进制的值,所以把数一位一位放进去就好了
//注意低位和高位
MOV HEX1,54H ;暂存数放到低位
MOV HEX0,53H ;暂存数放到高位
INC R1
MOV A,@R1 ;取一位放到A
ADD A,HEX1 ;相加后放到低位
MOV HEX1,A
MOV A,#0 ;计算高位
ADDC A,HEX0 ;
MOV HEX0,A ;相加后放到高位
//计算阶段
MOV 54H,#0
MOV 53H,#0
MOV A,HEX1 ;取低位×10
MOV B,#10
MUL AB
MOV 54H,A ;暂存低八位
MOV 53H,B ;暂存高八位
MOV A,HEX0 ;取高位×10
MOV B,#10
MUL AB ;MUL的结果高8位放在B,低8位放在A
ADD A,53H ;将计算得到的低八位和上次计算得到的高八位相加
MOV 53H,A
DJNZ R2,L1
FLOWOUT: SETB OV
STOP: SJMP $
END ;程序结束
1)方法一:借用二进制移位
//在寄存器中8位二进制数与2位十六进制数是一个东西
//所以我们要做的只是把十六进制数看作二进制的数一位一位用RLC取出
//分别放到三个寄存器中即可
MOV R0,#0C8H
MOV R1,#0A1H
CLR A
MOV R2, A ;存转换后的十进制数高位
MOV R3, A ; 存转换后的十进制数千百位
MOV R4, A ; 存转换后的十进制数十个位
MOV R5, #16 ;共转换十六位二进制数
LOOP:
//注意RLC是左移一位,尾部的值是由当前cy的值进上去的,头部的值再移到cy中更新cy
//低位与高位为一个整体,所以低位左移去出的cy补到高位尾部,形成一个整体
CLR C
MOV A, R1 ;从低位开始
RLC A
MOV R1, A
MOV A, R0 ;高位尾部的进位取决于低位左移出的cy
RLC A
MOV R0, A
//之后一位一位往上加即可
MOV A, R4 ;送到BCD码的位
ADDC A, R4 ;自身相加,即为×2操作
DA A ;十进制调整,变成BCD码
MOV R4, A
MOV A, R3
ADDC A, R3 ;使上一次十进制调整的结果导致进位加到这一位上
DA A
MOV R3, A
MOV A, R2
ADDC A, R2 ;使上一次十进制调整的结果导致进位加到这一位上
MOV R2, A ;不必再十进制调整,两种进制小于10时相等
DJNZ R5, LOOP ;共转换十六位二进制数
2)方法二:位权法十六进制转十进制:
设十六进制数:H3,H2,H1,H0四位
十进制=16^3 * H3+16 ^2 * H2+16 *H1+H0
提取16得:16 *(16 *(16 * H3+H2)+H1)+H0
此时可以使用循环来编写程序了,但因为乘16不能直接用MUL,所以需要对自身H0自加4次达到16 *H0效果
ORG 0000H ;伪指令,定义下面的指令所在地址,此句为主程序开始地址
LJMP MAIN ;无条件转移到MAIN
MAIN:
HEX0 EQU 30H ;存16进制高八位,这里对应DPTR,便于调试
HEX1 EQU 31H ;存16进制低八位
DEC0 EQU 40H
DEC1 EQU 41H
DEC2 EQU 42H
MOV HEX0,#12H
MOV HEX1,#34H
MOV R0,#30H //注意这里R0存的是数30H,这样INC R0就是指向下一个,@R0才是他的元素的值
MOV R1,#60H
MOV R2,#3
MOV R3,#3
MOV R4,#4
L0: //一位一位拿出来,放到以60H开始的地址中
MOV A,@R0
ANL A,#0F0H
SWAP A
MOV @R1,A
INC R1
MOV A,@R0
ANL A,#0FH
MOV @R1,A
INC R1
INC R0
DJNZ R2,L0
MOV R1,#60H //重新指向开头
MOV DEC2,@R1 //先拿出第一个数
INC R1
L1:
MOV 50H,@R1
INC R1
MOV R4,#4 //别忘了
L2: //乘16
CLR C
MOV A,DEC2
ADDC A,DEC2
DA A
MOV DEC2,A
MOV A,DEC1
ADDC A,DEC1
DA A
MOV DEC1,A
MOV A,DEC0
ADDC A,DEC0
DA A
MOV DEC0,A
DJNZ R4,L2
L3: //加
CLR C
MOV A,50H
ADDC A,DEC2
DA A
MOV DEC2,A
MOV A,DEC1
ADDC A,DEC1
DA A
//MOV DEC1,A
MOV A,DEC0
ADDC A,DEC0
DA A
MOV DEC0,A
DJNZ R3,L1
SJMP $ ;转到该指令的开头开始执行
END ;程序结束