问题:在使用div做除法的时候,可能会出现结果的商过大超过寄存器所存储的范围,这个错误称为除法溢出。
解决除法溢出有一个公式:
X:被除数,范围:[0, FFFFFFFF]
N:除数,范围:[0, FFFF]
H:X高16位,范围:[0, FFFF]
L:X低16位,范围:[0, FFFF]
int():描述性运算符,取商,比如,int(38/10) =3
rem():描述性运算符,取余数,比如,rem(38/10)= 8
公式:X/N = int(H/N) * 65536 +[rem(H/N) * 65536 + L] / N
解决思路:
1,传入参数为数据的高位,数据的低位和除数
2,结果:
商的高位为 int(H/N) * 65536
商的低位为[rem(H/N) * 65536 + L] / N的商
余数为[rem(H/N) * 65536 + L] / N的余数
3,过程:
(1)首先,把数据高位传入ax,除数传入cx,然后div cx,
ax的值为int(H/N) ,就可以获得结果的高位
(2)然后,dx的值为rem(H/N),一个数乘以65536相当于左移16位,相当于一个32位数据的高16位,div的用法是被除数的高位存在DX,被除数的低位存在AX,所以这个时候dx已经存了数据的高位
(3)最后把数据的低位传入AX,div cx,商为结果的低位,余数为结果的余数。
编写代码:
主函数
;计算1000000/10=F4240H/0AH,结果为186A0H
mov ax,4240h;数据的低位
mov dx,0fh;数据的高位
mov cx,0ah;除数
call divdw;调用子函数
mov ax,4c00h
int 21h
子函数为
;参数
;(ax)=dword型的数据的低16位
;(dx)=dword型的数据的高16位
;(cx)=除数
;返回
;(dx)=结果的高16位
;(ax)=结果的低16位
;(cx)=结果的余数
divdw:
push si
push bx;保存现场
mov bx,ax
mov ax,dx;把数据的高位传入AX
mov dx,0
div cx;结果AX的数值为结果的高位,DX的数值为rem(H/N)
mov si,ax
mov ax,bx;把数据的低位传入AX
div cx
;此时div cx相当于[rem(H/N) * 65536 + L] / N
;结果AX的数值为结果的低位,DX的数值为结果的余数
mov cx,dx
mov dx,si
pop bx;恢复现场
pop si
ret;函数返回
call指令
执行call指令过程
(1)将当前的IP或CS和IP压入栈中
(2)转移
call 标号
相当于
push IP
jmp near ptr 标号
call far ptr 标号
相当于
push CS
push IP
jmp far ptr 标号
call word ptr 内存单元地址
相当于
push IP
jmp word ptr 内存单元地址
例子:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
;执行后,(IP)=0123h,(sp)=0EH
call dword ptr 内存单元地址
相当于
push CS
push IP
jmp dword ptr 内存单元地址
例子:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
call dword ptr ds:[0]
;执行后,(CS)=0,(IP)=0123h,(sp)=0cH
ret和retf
ret指令用栈中的数据,修改IP的内容,从而实现近转移
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移
call和ret配合使用
具有子程序的源程序的框架如下:
assume cs:code
code segment
main:
call sub1
:
:
mov ax,4c00h
int 21h
sub1:
:
:
call sub2
:
:
ret
sub2:
:
:
ret
code ends
end main