SETB STAT.7 LJMP EXIT ; ------------------
KO_NE_DONE: ; KEY OPERATOR, NOT EQUAL, DONE ; 完成相应的操作后,更新STAT到当前状态
; 取回 INPUT ,并减去 10H ,成为STAT要求的操作符表示 MOV A, INPUT CLR C SUBB A, #10H
; 运算符信息保存在 STAT 的 4,5位 ; 先将4,5位清0
ANL STAT, #0CFH ; #1100 1111B ORL STAT, A ; 设置4,5位 ; 设置新的计算器状态
ANL STAT, #0F0H ; 清除状态(低4位) SETB STAT.3 ; 操作符号状态
RET ; KEYPRESSED 返回 ; -------- KOP1:
; 如果按了第一个数字之后按了操作符 ; 则首先将当前显示缓冲区里的数字 ; 拼合为3字节浮点数 ; 保存在NUM1位置
; RAWIN 保持不变,因此计算器显示的仍然为 ; 第一个操作数
MOV R0, #RAWIN ; 需要进行拼凑的数字 MOV R1, #NUM1 ; 目的 LCALL MAKENUM SJMP KO_NE_DONE KOP2:
; 如果按了第二个数字之后按了操作符, ; 首先计算前面的结果,然后结果作为 ; 第一个数, 并设置状态为操作符 ; 显示区域的数据为前面操作的结果 ; 即:需要将3字节的浮点数结果转化 ; 为可以显示的RAWIN格式。
; 创建第二个操作数 MOV R0, #RAWIN MOV R1, #NUM2 LCALL MAKENUM ; 执行计算 LCALL CALCULATE
; 结果默认已经存储于到NUM1位置
; 但是需要将其转换为RAWIN形式用于DISPLAY子程序的显示 LCALL RES2RAW ; NOTE: RES2RAW SJMP KO_NE_DONE KOP3:
; 按了一个操作符后又按了另一个操作符,则直接忽略原来的 ; 前面已经设置了操作符状态,此处无需进行任何操作 SJMP KO_NE_DONE KOP0:
; 按了等号之后按的操作符,则运算结果直接作为第一个 ; 操作数,因为按等号的时候已经进行了结果运算和显示 ; 所需要的准备工作(将浮点数转换为RAWIN形式) ; 因此这里不需要再作其他工作 SJMP KO_NE_DONE
; ======================================================= EXIT: SJMP $
; =======================================================
; ======================================================= MAKENUM: ; NOTEE!!! ; [R0] 为RAWIN
; [R1] 为目标,NUM1 OR NUM2 ; 先决条件:见前面
; 后决条件:NUM1中为二进制浮点数(3字节,补码形式)
; 转换结果,RAWIN形式的数字被转换为3字节二进制浮点数 MOV A, R0
MOV R3, A ; 保存源位置
MOV A, R1
MOV R4, A ; 保存目的位置
MOV R2, #00H ; 小数点位置
; 保存 DCOUNT ,子程序结束后 DCOUNT ; 和 [R0] 内容应该不变 PUSH DCOUNT
; 如果 DCOUNT 为零,则就是0 MOV A, DCOUNT JZ VALZERO
SJMP MN_DC_NZ ; DCOUNT NOT ZERO ; ------------------ ; 结果为0 VALZERO:
; 三个字节均设置为0 MOV @R1, #00H INC R1
MOV @R1, #00H INC R1
MOV @R1, #00H
LJMP MAKENUM_DONE ; -----------------------
MN_DC_NZ: ; MAKENUM, DCOUNT, NOT ZERO ; 判断是否以0开始,是则为纯小数 MOV A, @R0 JZ PUREDEC
; 不是纯小数,则从第一位开始计算数字个数, ; 直到遇到小数点或者输入数据结束(即是个整数) NONPUREDEC:
; 在计算指数的同时进行尾数的创建 INC R1 ; 暂时忽略第一个指数字节
; POSB 为 0 则进行高字节创建 CLR POSB FINDPNT:
MOV A, @R0 ; 取数 ; 更新 R0 ,指向下一个 INC R0
; 如果为小数点(用0FFH表示的一个字节), ; 则计数结束,否则继续 CJNE A, #0FFH, NEXTFP
NDMAN_CONT: ; NON DECIMAL MANTISSA, CONTINUE ; 小数点找到,继续创建尾数的BCD码 ; 指数已经保存于 R2 DEC DCOUNT MOV A, DCOUNT ; 出口
JZ NPD_DONE ; NON PURE DECIMAL DONE
MOV A, @R0 ; 取数
JB POSB, LOWER4_2 ; 创建低4位 ; ------------- ; 高4位 SWAP A MOV @R1, A
INC R0 ; 指向下一个,继续判断 SJMP NDMAN_CONT ; ------------- LOWER4_2: ; 低4位
MOV B, @R1 ; 取回高位 ORL A, B ; 整合为1个字节 MOV @R1, A ; 保存回去 CLR POSB ; 接下来是高4位 INC R0 ; 下一个源 INC R1 ; 下一个目的
SJMP NDMAN_CONT
; --------------------------------------- NEXTFP:
INC R2 ; 整数个数加一
; 将这个数字组合为BCD码
JB POSB, NUMLOWER4 ; 组合低位(POSB为1)?
; 组合高位,之后还要进行低位组合,不需要更新指针 SWAP A MOV @R1, A
SETB POSB ; 高位已经组建 SJMP NEXTFP1
NUMLOWER4:
; 取回已经组建了高字节的数据 MOV B, @R1 ; 加上低4位 ORL A, B ; 再保存回去 MOV @R1, A ; 更新目的指针 INC R1
; 接下来组建新的字节的高位 CLR POSB
NEXTFP1:
DEC DCOUNT ; 输入数据计数减一 ; 数据是否耗尽 MOV A, DCOUNT
JZ NPD_DONE ; 没有碰到小数点,是个整数 ; 否则还有输入数据等待检验,继续 SJMP FINDPNT
NPD_DONE: ; NON PURE DECIMAL DONE ; 数字组建结束,指数在R2中 MOV A, R4
MOV R1, A ; 恢复目的指针到初始值,以存放指数 MOV A, R2 ; 取指数
MOV @R1, A ; 保存在目的的第一个字节
LJMP MAKENUM_DONE ; 跳到结束操作
; ----------------------------------------------------
PUREDEC: ; 纯小数的情况
; 计算小数点后0的个数,以求得指数 INC R0 ; 指向小数点
; 相应的减少数字个数计数器,到零即表示数据处理完毕 DEC DCOUNT
; MOVE FROM 07.25,001 COUNTZERO: INC R0 ; 下一个
; 取一个数就减少DCOUNT
DEC DCOUNT ; MOVE TO, 07.25,001
MOV A, @R0 ; 取出 JZ PUREZERO ; 为零,计数
; 非零数字遇到,开始创建指数 ; 0个数在R2中,移到A后取其补码 MOV A, R2 CPL A
INC A ; 取反加一即得到补码 ; 最高位是符号位,为0 CLR ACC.7 ; 存储第一个字节 MOV B, R4 MOV R1, B MOV @R1, A