(二十五)数值显示和除法溢出问题--汇编笔记

汇编语言

Posted by YiMiTuMi on April 15, 2020

解决除法溢出问题

例:

mov bh, 1

mov ax, 1000

div bh

进行8位除法,结果商为1000,而1000在al中放不下。

在使用div指令做除法的时候,很可能发生:结果的商过大,超出了寄存器所能储存的范围。当CPU执行div等除法指令的时候,如果发生这样的情况,将引发CPU的一个内部错误,这个错误被称为:除法溢出

子程序描述:

名称:divdw

功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。

参数:

   (ax) = dword型数据的低16位

   (dx) = dword型数据的高16位

   (cx) = 除数

返回:

   (dx)= 结果的高16位
   	
	(ax) = 结果的低16位
 
    (cx) = 余数

例:计算1000000/10 (F4240H/0AH)

mov ax, 4240H

mov dx, 000FH

mov cx, 0AH

call divdw

结果:(dx)= 0001H, (ax) = 86A0H, (CX) = 0

提示:

给出一个公式:

X:被除数,范围[0, FFFFFFFF]

N:除数,范围[0, FFFF]

H:X高16位,范围[0, FFFF]

L:X低16位,范围[0, FFFF]

int(): 描述性运算符,取商

rem(): 描述性运算符,取余数

公式:X/N = int(H/N) * 65536 + [rem(H/N) * 65536 + L] / N

 1)其实 65536 就是 10000H,相当于 2^16,也就是说是乘以 2^16,意思就是左移16位。

 2)int(H/N) 进行的是16位的除法结果为32位的,然后乘上65536就相当于除法运算的高16位即dx。

 3)式中 int(H/N) 和 rem(H/N) 代表着X的高16位的商和余数。

 4)等式右边的 int(H/N)*65536 表示将 H/N 的商作为最终结果商的高位字。

 5)rem(H/N)*65536+L 表示将 H/N 的余数左移16位,形成一个新的dword数据的高16位,L作为低16位。

[rem(H/N) * 65536 + L]一个新的32位数据。

rem(H/N)*65536+L相当于rem(H/N)高16位和L低16位组成的32位数据。

(dx)= int(H/N)*65536 //相当于当高位储存

(ax) = (rem(H/N)*65536+L)/N的商 32位除法高16位存放dx,低16位存放L

(cx) = (rem(H/N)*65536+L)/N的余数

完整程序:

assume code

code segment

	start:  mov ax, 4240H
			mov dx, 000FH
			mov cx, 0AH
			call divdw

			

	divdw:  //公式前半部分计算
			push ax		

			mov ax, dx    
			mov dx, 0   //32除法将高位置零,保证ax/cx

			div cx       // H/N  ax保存商
			
			mov bx, ax   //保存商
			

			//上次div cx结果的余数为dx,下面32位除法中直接用作被除数的高位
			pop ax      //获取32位除法的低16位给ax
			
			div cx      //计算后的商保存在ax中 直接作为最后返回结果的商的低位

			mov cx, dx   //保存返回的余数
			mov dx, bx   //保存返回的商的高位
			
code ends

end start
		

x/n = (dx/cx的商(这是8位除法,被除数16位))(高位) + [(dx/cx的余数)(高位) + ax(低位)]/cx(16位除法被除数32位数据)

数值显示

data段中的数据以10进制形式显示。(将10进制数据转化为ASCII码保存)

子程序描述:

名称:dtoc

功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾。

参数:(ax)= word 型数据 ds:si 指向字符串的首地址

assume cs:code

data segment
	
	db 10 dup (0) 

data ends 

code segment

	start: ax, 12666
	       mov bx, data
		   mov ds, bx
		   mov si, 0
		   call dtoc
		   mov ax, 4c00H
		   int 21H
		
	dtoc: mov bx, 10
		  mov dx, 0
		  div bx
		  mov cx, ax     //32/16的除法
		  add dx, 30H
		  mov ds:[si], dl
		  jcxz cx
		  inc si
		  jmp short dtoc
		
       s: ret	
		
code ends

end start

黄玫瑰 – 抱歉、对不起