// 参考:https://blog.csdn.net/belous_zxy/article/details/81779660
// https://blog.csdn.net/qq_52516071/article/details/124696409
ORG 0000H
LJMP INIT
ORG 0003H //外部中断0
LJMP INT0SUB
ORG 0013H //外部中断1
LJMP INT1SUB
ORG 0100H
INIT: CLR P1.0 //控制端复位
CLR P1.1
MOV DPTR,#TABLE //指向表头
MOV 50H,#05H //循环次数
MOV 51H,#7FH //位选信号
MOV TMOD,#50H //工作模式
MOV TL1,#00H //初始化
SETB EA //启动总中断
SETB EX0 //启动外部中断0
SETB EX1 //启动外部中断1
SETB TR1 //启动计数器1
TRANS: SETB TR1 //启动计数器1
; MOV A,TL1 //16进制转10进制
; MOV B,#10
; DIV AB
; MOV 40H,B //个位
; MOV B,#10
; DIV AB
; MOV 41H,B //十位
; MOV 42H,A //百位
MOV 38H, TH1
MOV 39H, TL1
MOV R6, 38H
MOV R7, 39H
MOV R4, #00H
MOV R5, #10
LCALL UIDIV
MOV 40H,R5 //个位
MOV R5, #10
LCALL UIDIV
MOV 41H,R5 //十位
MOV R5, #10
LCALL UIDIV
MOV 42H,R5 //百位
MOV R5, #10
LCALL UIDIV
MOV 43H,R5 //千位
MOV R5, #10
LCALL UIDIV
MOV 44H,R5 //万位
MOV R5, #10
LCALL UIDIV
MAIN: MOV A,51H //位选信号
MOV P0,A //输出位信号
SETB P1.1 //上升沿
CLR P1.1
MOV A,40H //段选信号
MOVC A,@A+DPTR
MOV P0,A //输出段信号
SETB P1.0 //上升沿
CLR P1.0
MOV 40H,41H //改变段选信号
MOV 41H,42H
MOV 42H,43H
MOV 43H,44H
MOV A,51H
RR A //位选右移
MOV 51H,A
LCALL DELAY //延时1ms
DJNZ 50H,MAIN //循环5次
MOV 50H,#05H //循环次数复位
MOV 51H,#7FH //位选信号复位
SJMP TRANS
INT0SUB:CLR TR1 //启动/停止
RETI
INT1SUB:MOV TL1, #00H //清0
MOV TH1, #00H
RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH //段选表
DELAY: MOV 30H,#2 //延时1ms
MOV 31H,#234
NEXT: DJNZ 31H,NEXT
DJNZ 30H,NEXT
RET
;无符号双字节数除法子程序 UIDIV
;被除数存R6(高位)、R7(低位),除数存R4(高位)、R5(低位)
;运算完成后,R6、R7存放商,R4、R5存放余数
UIDIV:
CJNE R4,#00H,DIV_H1 ;判断除数高8位是否为00H
CJNE R6,#00H,DIV_H2 ;判断被除数高8位是否为00H
ALLDIV_L: ;情况0:除数、被除数高8位均为00H
MOV A,R7
MOV B,R5
DIV AB
MOV R7,A
MOV R5,B
RET ;调用DIV指令结束
DIV_H1: ;情况1:除数高8位非00H,即商肯定是单字节(8位以内,R6=00H)
CLR A
XCH A,R4 ;除数高8位R4清零
MOV R0,A ;R0暂存R4内容
MOV B,#08H ;移位相减共08H次
UIDIV_LOOP1:
MOV A,R7
ADD A,R7
MOV R7,A
MOV A,R6
RLC A
MOV R6,A ;被除数16位左移,最低位取0,最高位移至C
MOV A,R4
RLC A
MOV R4,A ;除数高8位R4左移,最低位取被除数高8位的最高位,最高位移至C(C肯定为0)
;*R4存储的是被除数左移的超出位,R6、R7存储的是被除数左移的剩余位,当08H次循环后,R7必然是00H,被除数变为余数在R4、R6
MOV A,R6
SUBB A,R5 ;判断当前R5和R6大小,(即判断除数低八位是否可以减去)
MOV A,R4
SUBB A,R0 ;判断当前R4是否大于原始值,这里可能是借位减法(即判断除数高8位是否可以减去)
JC R4_HIGH ;大于,不能减去余数
R4_EQU_LOW: ;满足小于等于
MOV R4,A
MOV A,R6
SUBB A,R5
MOV R6,A
INC R7 ;减去余数,商值加一
R4_HIGH:
DJNZ B,UIDIV_LOOP1
CLR A
XCH A,R6
MOV R5,A ;余数后8位移至R5,并清空R6
RET
DIV_H2: ;情况2:除数高8位为00H,被除数高8为非00H,则余数肯定是单字节(8位以内,R4=00H)
MOV A,R5
MOV R0,A ;R0暂存除数
MOV B,A
MOV A,R6
DIV AB ;被除数高8位除以余数
JB OV,UIDIV_END ;检查到除数低8位也为00H,直接结束程序(OV=1)
MOV R6,A
MOV R5,B ;商存在R6,余数存在R5
MOV B,#08H ;移位相减共08H次
UIDIV_LOOP2: ;低8位运算
MOV A,R7
ADD A,R7
MOV R7,A ;被除数低8位R7左移,最低位取0,最高位移至C
MOV A,R5
RLC A
MOV R5,A ;高8位运算的余数作为剩余值继续运算,左移,最低位取被除数低8位的最高位,
JC UIDIV_NEXT ;左移移出到了C,必然可以相减
SUBB A,R0 ;判断当前值是否大于余数
JNC RE_EQU_LOW ;满足小于或等于
RE_HIGH: ;大于,不能减去
DJNZ B,UIDIV_LOOP2
RET
UIDIV_NEXT:
CLR C
SUBB A,R0 ;减去除数,必然存在借位 C=1
RE_EQU_LOW:
MOV R5,A ;更新当前剩余值
INC R7 ;成功减一次除数,商的低8位加一
DJNZ B,UIDIV_LOOP2
UIDIV_END:
RET
END
完整资料打包(含仿真):