RL A ;A←A×2 ADD A,R3 ; A←3×R3 JC NEXT ;有进位则转移 MOV DPTR,#BRTAB1 ;分支表1的首地址 JMP @A+DPTR
NEXT: DEC A ;调整A的值 DEC A
MOV DPTR,#BRTAB2 ;分支表2的首地址 JMP @A+DPTR
BRTAB1:LJMP ROUT00 ;转向分支0 ┆
LJMP ROUT85 ;转向分支85 BRTAB2:LJMP ROUT86 ;转向分支86 ┆
LJMP ROUT127 ;转向分支127
3-10 外部数据RAM中有一个数据块,存有若干字符数字,首地址为SOURCE,耍求将该数据块传送到内部RAM以DIST开始的区域,直到遇到字符“$”时结束(“$”也要传送,它的ASCII码为24H)。
解:对于这种以特征字为结束符的数据块传送程序,一般都采用先比较判别,后传送的方式编程,以免在数据块长度为0时出间题。但本题中耍求结束符也传送,所以,可以先传送后比较,这样程序较为简短。
SOURCE DATA 3000H DIST DATA 20H
MOV DPTR,#SOURCE ;源数据块首地址
MOV R0,#DIST ;目的数据区首地址 LOOP: MOVX A,@DPTR ;取一个数据 MOV @R0,A ;传送至内部RAM INC DPTR ;修改地址指针 INC R0
CJNE A,#24H,LOOP ;不为结束符则循环 SJMP $ ;结束 END
3-11 内部数据RAM中有一个数据块,首地址为BLOCK。对其中的数据进行奇偶校验,凡是满足奇校验的数据都要送到外部数据区以EBLOCK为首的区域,该区域在256B范围内。原数据块长度存于LEN单元。
解:在MCS-51系统中,奇偶标志位是按照累加器A的内容设定的,并在每次对累加器操作以后进行检测和修改。当A中1的数目为奇数时P=1,否则P=0。可以用位检测指令来判断P的值。程序如下:
LEN DATA 20H BLOCK DATA 21H EBLOCK DATA 00H
MOV R0,#BLOCK ;源数据块首地址
MOV R1,#EBLOCK ;目的数据区首地址; MOV R2,LEN ;数据块长度
MOV A,R2
JZ FINISH ;长度为0则结束 LOOP: MOV A,@R0 ;取一个数 INC R0 ;修改源地址指针 JNB P,NEXT ;P=0,不传送,转NEXT MOVX @R1,A ;P=1,传送 INC R1 ;修改目的地址指针 NEXT: DJNZ R2,LOOP FINISH:SJMP $ END
3-12 将上题中数据块内的数据,凡满足奇校验的传送到外部RAM 256B以内从BLCOK1开始的区域,凡满足偶校验的数据,传送到以BLOCK2开始的区域。原数据块长度仍存于LEN单元。
解:这个题目编程时需要3个地址指针分别指向BLOCK,BLOCK1,BLOCK2三个数据区。但MCS-51指令系统中可以用于寄存器间接寻址的寄存器只有R0和R1两个。所以要采取措施来保存地址。可用的办法很多。一种方法是利用MCS-51系统有4组工作寄存器,而每组都有R0和R1两个指针的特点,在需要第3个地址指针时改变到另一个工作寄存器组,用完以后再恢复到原来的工作寄存器组。用这样的方法最多可以直接得到8个地址指针。另一种方法是利用堆栈来保存地址。当然还可以有其它的方法。这两种解法的程序如下:
解法一:
LEN DATA 20H BLOCK DATA 21H BLOCK1 DATA 50H BLOCK2 DATA 80H CLR RS0
MOV R0,#BLOCK ;第一个数据指针
MOV R1,#BLOCK1 ;第二个数据指针 MOV R2,LEN ;R2存数据块长度 SETB RS0 ;转到工作寄存器组1 MOV R1,#BLOCK2 ;第三个数据指针 CLR RS0 ;回到工作寄存器组0 LOOP: MOV A,@R0 ;取一个数 INC R0 ;修改第一个指针 JNB P,NEXT1 ;偶校验转NEXT1
MOV @R1, A ;奇校验,送至BLOCK1区 INC R1 ;修改第二个指针 SJMP NEXT2
NEXT1:SETB RS0 ;转转工作寄存器组1 MOVX @R1,A ;送至BLOCK2区 INC R1 ;修改第三个地址指针 CLR RS0 ;回到工作寄存器组0 NEXT2: DJNZ R2,LOOP ;未结束,循环
SJMP $
END 解法二:
MOV R0,#BLOCK ;第一个数据指针
MOV R1,#BLOCK1 ;第二个数据指针 MOV R2,LEN ;R2存数据块长度 MOV R3,#BLOCK2 ;第三个数据指针 LOOP: MOV A,@R0 ;取一个数 INC R0 ;修改第一个指针 JNB P,NEXT1 ;偶校验,转NEXT1
MOVX @R1, A ;奇校验,送至BLOCK1区 INC R1 ;修改第二个指针 SJMP NEXT2
NEXT1: PUSH 01H ;第二个地址指针进栈保护 PUSH 03H ;第三个地址指针进栈
POP 01H ;暂用R1作第三个地址指针
MOVX @R1,A ;传送至BLOCK2区 INC R3 ;修改第三个地址指针 POP 01H ;恢复第一个地址指针 NEXT2: DJNZ R2,LOOP ;未结束,循环
SJMP $
END
注意工作寄存器的进栈、出栈操作,不能用PUSH R1,POP R3等指令,而要用它们的直接地址,如PUSH 01H,POP 02H等。
3-13设无符号数X存于内部RAM的VAR单元,Y存于FUNC单元。请按照以下要求编制程序:
并设2
仍为8位二进制数。
解:这个题可以直接用比较条件转移指令来完成。采用适当的比较方法和比较顺序,可以使程序写得简洁些。
VAR DATA 20H FUNC DATA 21H
MOV A,VAR ;取X到A CJNE A,#21,00H ;与21比较 JC NEXT1 ;X≤20,转至NEXT1 CJNE A,#40H,00H ;与40比较 JNC NEXT2 ;X≥40转至NEXT2 ;20 RLC A ;A=2 SJMP NEXT2 NEXT1: CPL A ;A= SJMP $ END NEXT2: MOV FUNC,A ;存入Y 3-14 外部数据RAM从2000H到2100H有一个数据块,现要将它们传送到从3O0OH到3100H的区城。试编写有关程序。 解:外部数据区传送只能利用MOVX A,@DPTR和MOV @DPTR, A指令,数据指针只有一个。而现在需要两个数据指针:源指针和目的指针。因此,亦要采取措施来保存地址。在本例中,两个数据区地址低8位相同,因而只需对高8位地址分别保存即可。程序如下: MOV R2,#20H ; 源数据区地址高8位 MOV R3,#30H ; 目的数据区地址高8位 MOV DPL,#00H ; 数据区地址低8位 LOOP: MOV DPH,R2 ; 形成源地址 MOVX A,@DPTR ;取一个数 MOV DPH,R3 ; 形成目的地址 MOVX @DPTR,A ; 传送一个数 INC DPL ; 修改低8位地址 CJNE DPL,#00H,LOOP INC R2 ; 变为21H INC R3 ; 变为31H MOV DPH ,P2 ; 再传送一个数 MOVX A,@DPTR ;A←(3100H) MOV DPH,R2 MOV @DPTR,A ;(3100H)←A SJMP $ END 也可以利用堆栈来保存地址,下面是此题的另一种解法。 MOV DPTR,#1FFFH LOOP: INC DPTR MOVX A,@DPTR ;取一个数 PUSH DPH ;源地址高8位进栈 PUSH ACC ;暂存A MOV A,DPH ADD A,#10H ;形成目的地址高8位 MOV DPH,A POP ACC MOVX @DPTR,A ;传送一个数 POP DPH ;恢复源地址高8位 CJNE DPH,#21H,LOOP SJMP $ END 3-15 外部RAM从0OOOH开始有2k字节数据要转移到从2000H开始的区域。试编写有关的程序。 解:数据区转移若按数据区长度来进行,则需要用到减1指令。即每传送一次,长度计数器减1,减至0时传送结束。但MCS-51中没有16位减1指令,只有8位减1指令。所以长度超过256个字节时,便要采用多重循环来解决。程序如下: MOV R2,#00H ; 源数据区地址高8位 MOV R3,#20H ; 目的数据区地址高8位 MOV DPL,#00H ; 数据区地址低8位 MOV R4,#8 ;8*256=2048 LOOP: MOV DPH,R2 ; 形成源地址 MOVX A,@DPTR ;取一个数 MOV DPH,R3 ; 形成目的地址 MOVX @DPTR,A ; 传送一个数 INC DPL ;低8位地址加1 CJNE DPL,#00H,LOOP ;不到256个字节则循环 INC R2 ; 源地址高8位加1 INC R3 ; 目的地址高8位加1 DJNZ R4,LOOP ;不够8次则循环 SJMP $ END 3-16 外部数据RAM从2000H开始有100个数据,现要将它们移到从2030H开始的区城。编写有关的程序。 解:此时源数据区和目的数据区在地址上出现了重迭。在传送时注意不要把还没有传送的效据覆盖掉。为此,可以从源数据区的高端(2063H)先开始传送,然后地址逐渐减小,直到传送完毕。程序如下: MOV DPTR,#2000H ; 源数据区首地址 MOV A,#64H ; 长度为一百 MOV R2,A ; 存入R2 ADD A,DPL DEC A MOV DPL,A ;源数据区末端地址 LOOP: MOVX A,@DPTR ;取一个数 PUSH DPL ;源地址低8位进栈 PUSH ACC ;A内容进栈暂存 MOV A,DPL ADD A,#30H MOV DPL,A ;目的地址区低8位 POP ACC ;恢复A MOVX @DPTR,A ; 传送一个数 POP DPL ;恢复源数据区地址 DEC DPL ;源地址指针减1 DJNZ R2,LOOP ;未传送完则循环 SJMP $ END 3-17 从内部RAM的BLOCK地址开始有一个无符号数数据块,长度存于LEN单元。求出数据块中的最小元素,并将其存入MINI单元。要求使用比较条件转移指令CJNE。