51单片机:有符号/无符号双字节除法汇编程序(超详细)

2019-04-15 13:02发布

DIV只能用于两个单字节之间的除法,有时处理的数据是双字节大小,就需要单独写出双字节除法子程序。 实现的原理还是简单的列式模拟,但是汇编的细节更多。对熟练掌握汇编需要对二进制运算和移位操作非常熟悉。 >>过程注释写的非常详细了 ;有符号双字节数除法子程序 SIDIV ;正负数均用原码表示 ;需要 UIDIV 子程序 ;被除数存R6、R7,除数存R4、R5 ;运算完成后,R6、R7存放商,R4、R5存放余数 SIDIV: CLR F0 MOV A,R4 JNB 0E0H.7,DIV_POSTIVE1 DIV_NEGATIVE1: CPL F0 ;标记此次运算除数为负数 CLR A CLR C SUBB A,R5 MOV R5,A CLR A SUBB A,R4 MOV R4,A ;对除数取补码 DIV_POSTIVE1: MOV A,R6 JNB 0E0H.7,DIV_POSTIVE2 DIV_NEGATIVE2: CPL F0 ;得出运算结果的正负号 CLR A CLR C SUBB A,R7 MOV R7,A CLR A SUBB A,R6 MOV R6,A ;对被除数取补码 LCALL UIDIV ;开始运算 CLR C CLR A SUBB A,R5 MOV R5,A CLR A SUBB A,R4 MOV R4,A ;余数恢复原码(余数必须为正) SJMP NOT_CFUNC DIV_POSTIVE2: LCALL UIDIV ;开始运算 NOT_CFUNC: JNB F0,SIDIV_END ;运算结果为正,则直接结束程序 RESULT_NEGATIVE: CLR C CLR A SUBB A,R7 MOV R7,A CLR A SUBB A,R6 MOV R6,A ;运算结果为负,则把商恢复原码 SIDIV_END: 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