10.2 解决除法溢出的问题
给出的公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
参数: ax存放被除数低16 dx存放被除数高16 cx存放除数
分析:
*65536相当于进到高16位 rem(H/N)*65536不用算,因为算H/N的时候已经把这个结果算出来了,存放在dx,相当于只要计算H/N 和L/H
完整代码:
assume cs:code,ss:stack stack segment dw 10 dup(0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,20 mov ax,4240h mov dx,0fh mov cx,0ah call divdw mov ax,4c00h int 21h divdw: ;X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N ;分析 *65536相当于进到高16位 rem(H/N)*65536不用算,因为算h/n的时候已经把这个结果算出来了,存放在dx,相当于只要计算h/n 和l/n ;ax存放被除数低16 dx存放被除数高16 cx存放除数 push ax mov ax,dx ;取出高16位 mov dx,0 ;被除数高16位置0,因为要计算H/N div cx ;int()H/N 商结果存放ax,余数结果存放dx,一切都是那么的恰到好处 mov bx,ax ;存放结果 pop ax ;取出低16位 div cx ;L/N 商ax 余数dx mov cx,dx ;存储余数 mov dx,bx ;存储低16位 ret code ends end start
实验10.3 数值显示
这里要用到前面的子程序showptr(显示以0结尾字符串在显示器上),将数值显示出来。
我们也需要写一个通用的小程序dtoc,用来将数据转化为10进制的ASCII码
算法规则:
12345/10=1234 余数5 --> 5+30H=35H 入栈
1234/10=123 余数4 -->4+30H=34H 入栈
123/10=12 余数3 -->3+30H=33H 入栈
12/10=1 余数2 -->2+30H=32H 入栈
1/10=0 余数1 -->1+30H=31H 入栈 到此结束计算
然后统统出栈到data段之中就可以了。
最后再调用showptr小程序就可以显示到屏幕上了.
完整代码:
assume cs:code,ds:data,ss:stack data segment db 20 dup(0) data ends stack segment dw 20 dup(0) stack ends code segment start: mov bx,data mov ds,bx mov bx,stack mov ss,bx mov sp,40 mov ax,12345 mov si,0 call dtoc ;将word型数据转变成十进制字符串,字符串以0结尾,存放于data段 mov dh,12 mov dl,64 mov cl,02h mov si,0 call showptr ;显示字符串 dh是行,dl是列,cl是颜色,ds:si指向字符串首地址 mov ax,4c00h int 21h dtoc: push ax push bx push cx push dx push di push si mov bx,10;除数为10 mov di,0 ;计数器置0 s0: mov dx,0 ;被除数高位置0 div bx ;做除法 dx存放余数 ax存放商 add dx,30h ;余数加30h push dx ;存放ascii码,入栈 inc di ;计数器加1 ;判断商是否为0 mov cx,ax jcxz dtoc_ok jmp short s0 ;跳转回去继续做除法直到商为0 dtoc_ok: ;inc di mov cx,di ;计数器存进cx做循环 ;inc cx s2: pop ds:[si];出栈 弹出到data空间 inc si ;指针后移 loop s2 ;结束循环表示出栈成功 ;归还寄存器 pop si pop di pop dx pop cx pop bx pop ax ret showptr: ;将用到的寄存器统统存储一遍,后续结束小程序时全部返还 push di push dx push cx push si push ds push es push ax show: ;将字符串显示在屏幕上,dh是行,dl是列,cl是颜色,ds:si指向字符串首地址 ;1.首先计算显存位置 sub dh,1 ;dh减一 mov al,dh ;做乘法运算 mov ah,160 mul ah ;行数减一乘以160 最后将结果ax加上dl即可 mov dh,0 add ax,dx ;ax此时存放写入的地址位置 mov di,ax ;作为显存指针使用 mov ax,0b800h mov es,ax ;将显存地址写入es ;2.确定颜色属性 mov dh,cl ;将颜色属性赋值高位过去 ;3.写入字符串,ds:si指向字符串首地址,需要将字符串存放到dl中 show0: ;这里要利用jcxz了 mov ch,0 mov cl,ds:[si] jcxz show_ok mov dl,ds:[si] ;获取字符串字节 mov es:[di],dx ;将dx写入到es:[di]中去 也就是显存地址 inc si ;字符串指针后移 add di,2 ;显存地址后移 jmp short show0 ;跳转回去 show_ok:;出口 pop ax pop es pop ds pop si pop cx pop dx pop di ret code ends end start
效果如下图