马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
前提:
除法溢出处理方法:
比如ABCD DCBA/10在计算上必定溢出,故分为高十六位与低十六位,
先求出高十六位的商,然后余数作为低十六位的最高位,与低十六位一起看成新的数值继续求商,最后高十六位的商与低十六位一起重新合并成为新的数值,即为所求。
ABCDDCBA/10=ABCDDCB
拆分处理后:
0000 ABCD/10=ABC…D
000D DCBA/10=DDBC…A
然后高十六位的商与低十六位的商组合得ABCDDCB,即为所求。(想一想,其实这种思想小学就学了,回想一下我们做除法的步骤)
进制转换方法:
书上说的,十六进制或二进制转换十进制均为X*Y^N次方(X为当前位的数值,Y代表进制,N代表当前位,你懂的)
然后这是我的方法:
既然十进制数除以16或2直到商为0,然后自下向上分别取余组成一个数,那么相对的,其他进制也能这么做,所以嘛,看下面实例(躺在床上无意发现的,有错也正常)
例子数:902715864 (35CE59D8)
求十进制,当然除以十六进制的A(10)
35CE 59D8/A=0561 6F62…4(4)
0561 6F62/A=0089 BE56…6(6)
0089 BE56/A=000D C63B…8(8)
000D C63B/A=0001 609F…5(5)
0001 609F/A=0000 2343…1(1)
0000 2343/A=0000 0386…7(7)
0000 0386/A=0000 005A…2(2)
0000 005A/A=0000 0009…0(0)
0000 0009/A=0000 0000…9(9)
然后自下向上取余,组成一个新的数,就是十进制数。
从上面可以看出,此时十六进制与十进制完全一样(即使在计算机上),基于此情况,我们能在屏幕上显示十进制数,只要加上30H变成ASCII码即可。
问题来了:
从十六进制转换十进制来看,上述方法明显存在除法溢出,怎么办?
以本文一开始的除法溢出处理方法进行处理。
可一操作就有问题了,你会发现数据拆分之后求余根本得不到正确的结果。(本人已找到问题所在)
注意:本帖问题在代码下方,此处仅作本帖问题的由来。
以下是在显示器显示十进制数的源码,除上述问题外仍有瑕疵,请勿复制,及供参考。
ASSUME CS:CODE DS:DATA SS:STACK
DATA SEGMENT
DD 5940323,29304512
DB 16 DUP (1) ;存放被数据的每一位数字
DATA ENDS
STACK SEGMENT
DW 30 DUP(1)
STACK ENDS
CODE SEGMENT
START: ;各种初始化
MOV AX,DATA
MOV DS,AX
MOV AX,STACK
MOV SS,AX
MOV SP,20H
MOV AX,0E800H
MOV ES,AX
MOV CX,2
XOR SI,SI
XOR DI,DI
TWO:
PUSH CX
MOV AX,DS:[SI]
MOV DX,DS:[SI+2]
CALL FAR PTR SHOW_STR
ADD SI,4
POP CX
LOOP TWO
OK:
MOV CX,5
LOOP OK
MOV AX,4C00H
INT 21H
SHOW_STR:
PUSH DX
MOV CX,2 ;初始化S1模块执行次数
PUSH CX
MOV BX,10
S1: ;无需循环的指令被放在S1模块外
XOR DX,DX
DIV BX
ADD DL,30H
MOV DS:[SI+8],DL
INC SI ;SI寄存器记录了当前被处理的数据的位数
MOV CX,AX
JCXZ JUDGE
JMP S1
JUDGE:
POP CX ;控制S1模块执行次数
SUB CX,1 ;
JCXZ PRINTF ;若S1模块执行够两次,转到printf模块
POP AX ;若S1模块执行未够两次,则执行此处指令并转跳回S1模块
PUSH CX
JMP S1
PRINTF:
MOV CX,SI ;LOOP指令当CX为零就跳转,所以先执行该指令
SUB SI,1 ;然后(SI)-1保证读取正确的数据
MOV DL,2
XOR AX,AX
XOR DI,DI
S2:
MOV AL,DS:[SI+8] ;在显存写入数据
MOV ES:[DI],AL ;数据
MOV ES:[DI+1],DL ;颜色信息
SUB SI,1
ADD DI,2
LOOP S2
RETF
CODE ENDS
END START
呃,看到这里,我会跟你说,上面的代码有一个S1模块,那一段是错的,还没修改。
然后我想说的是,根据除法溢出处理方法,我会拆分数据。
例如 04A0 2314(77603604)
如果这个数据先把高十六位求余,再组合低十六位成为新的被除数X2314 (X为高十六位的余数)
此时可见,这个新的被除数直接做除法也可能会溢出。
所以我们得再拆分的更细一点,先和低十六位的前两位组合吧?(X23)
本帖问题来了:
有没有发现,(AX)=0YYY或00YY(Y为商),那么如何处理前面的0呢?
如果各位有自己笔算一下,你就会发现,寄存器数据不足四位则向前补0这个规矩真的很烦。
如果不处理会使数据产生偏差,尤其是二进制化十进制的时候。
个人精力和能力有限,故在此向各位请教。