汇编语言王爽第八部分(编写子函数,call和ret配合使用)

问题:在使用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

子函数为

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;结果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
发布了8 篇原创文章 · 获赞 0 · 访问量 78

猜你喜欢

转载自blog.csdn.net/qq_41955402/article/details/104309070