马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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这个规矩真的很烦。 如果不处理会使数据产生偏差,尤其是二进制化十进制的时候。
个人精力和能力有限,故在此向各位请教。
|