首页
社区
课程
招聘
[原创]汇编学习记录课程设计1之解决除法溢出
发表于: 2021-3-24 21:32 3683

[原创]汇编学习记录课程设计1之解决除法溢出

2021-3-24 21:32
3683

记录一下自己的学习过程
汇编语言(王爽)课程设计1:之解决除法溢出
作为一个打工人没有那么多整段的时间去完成一整个课程设计,能出一点是一点,但我还是大意了,感觉没写什么时间就没了,而其中最耗时间的不是写代码而是数学,写注释和写文档就TM离谱

 

言归正传,自代码的目的是解决div的除法溢出问题,为什么要解决这个问题?显示字符类型的数据好办,放进显存不麻烦,但数值类型的数据你要显示得不断除10取余,直到余数为0,在转化成字符(余数+30h)对32位数除以10很大可能ax放不下商所以自己定义一个函数进行除法解决溢出问题

 

源码
assume cs:code,ds:data,ss:stack
data segment
dd 140010 ,210412 ,152321 ;offset 0
;0002 22ea ;0003 35ec ;0002 5301

 

dw 65535 ,345 ,657 ;offset 12
; ffff ;0159 ;0291

 

;result int(X)
;0002 ;0261 ;00e7
;resul rem(X)
;22ec ; 0133 ;022a
data ends

 

stack segment
db 64 dup (0)
stack ends

 

code segment
start: mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov si,0
mov di,12
mov cx,3

 

next: push cx
mov ax,[si]
mov dx,[si+2]
mov cx,[di]
call divdw
pop cx
add si,4
add di,2
loop next

 

;注释建议跳过,恶心的自己了
;divdw dx=XH,ax=XL,cx=N
;int(x/N) x/N的整数部分,rem(x) x/N的余数部分
;int(X/N)=int(XH/N)2**16+int(rem(XH/N)216+XL)
;rem(X/N)=rem(rem(XH/N)*2
16+XL)
;公式 X/N=int(XH/N)2**16+[rem(XH/N)216+XL]/N
;引申 int(X/N)=int(XH/N)*2
16+int([rem(XH/N)2**16+XL]/N)
;引申 rem(X/N=rem([rem(XH/N)
216+XL]/N)
;证明(写的太啰嗦看附注5吧)
;case
;X=XH*2
16+XL
;XH=int(XH/N)N+rem(XH/N)
;so
;X/N=int(XH/N)
N2**16/N+(rem(XH/N)216+XL)/N
;rem(X/N)=rem(rem(XH/N)216+XL)
;int(X/N)=int(XH/N)*2
16+int(rem(XH/N)2**16+XL)
;现在的问题是上一步的int(rem(XH/N)
216+XL)<=65535(216-1即除法结果是否都在低位),是的话
;dx=int(XH/N),ax=int(rem(XH/N)2**16+XL)
;
;int(rem(XH/N)
216+XL)<=65535的证明
;case
;rem(XH/N)<N-1
;so
;rem(XH/N)*2
16<(N-1)2**16

 

;cace
;rem(XH/N)216<=(N-1)216
;XL<=2**16-1
;so
;rem(XH/N)
216+XL<=N*(216-1)+N-1
;int(rem(XH/N)2**16+XL)<=int(N(2**16-1)+N-1)

 

;case
;int(N(2**16-1)+N-1)=(N(216-1)+N-1)/N=(N*(216-1))/N+N-1/N=216-1=65535
;so
;int(rem(XH/N)*2
16+XL)<=65535 得证
;

 

divdw: push bp
mov bp,sp
push ax ;save XL
mov ax,dx
mov dx,0
div cx ;result dx=rem(XH/N) ax=int(XH/N)
push ax ;save int(XH/N)

 

;(rem(XH/N)216+XL) / N
mov ax,[bp-2] ;由于dx=rem(XH/N)已就位,只需设置ax=XL
div cx ;result dx =rem(rem(XH/N)2**16+XL)=rem(X/N),ax=int((rem(XH/N)2*16+XL)/N)
mov cx,dx
mov dx,[bp-4]
;cx=rem((rem(XH/N)
216+XL) / N)rem(X/N)
;dx=int(XH/N)
;ax=int((rem(XH/N)
2*16+XL) / N)
mov sp,bp
pop bp
ret

 

code ends

 

end start

 

是否正确呢?
1.先跳到call divdw,第一组140010/65535,输入应为
ax=22ea,dx=0002,cx=ffff
图片描述
图片描述

 

2.输入正确看一下函数结果,不跳进去了执行到函数下一条命令pop cx g cs:1e,结果应为 ax=0002H ,dx=0000H,cx=22ecH
图片描述
3.重复上面的命令看之后的计算是否正确

 

a.
210412/345
In: 应为ax=35ecH,dx=0003H,cx=159H
图片描述

 

Out: 应为ax=261H,dx=0000H,cx=133H
图片描述
b.152321/657
In: 应为ax=5301H,dx=0002H,cx=0291H
图片描述
Out: 应为ax=00e7H,dx=0000H,cx=022aH
图片描述

 

三次除法都符合预期,基本判定是正确的。
问什么说是基本?
此程序的目的是解决除法溢出而自己定义了个除法,但三个结果dx=0,也就是说这三个除法你用div也能做,没产出溢出,你咋知道div真的溢出时这玩意是否靠谱
所以请自行验证,比如加一组65536/1(记得修改cx)看看是否符合预期,(对我就是懒改,写报告比写代码累多了)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 39
活跃值: (2901)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主不会用32位寄存器做除法吗?另外堆栈段的定义也不规范,应该在segment后面加stack,这样就用不着手工对ss及sp初始化了。
2021-3-24 22:05
0
雪    币: 28
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
被除数用了两个寄存器,结果商和余各放在一个寄存器,div 1 结果是被除数原值一个寄存器肯定存不下会除法溢出,把ax换成eax,dx换成edx问题也还是是一样,关于栈的问题,仔细看确实忘了设定sp,加上mov sp,40h.至于手工的问题不打算解决反正现在还没问题,还能提醒我栈的初始化这件事。感谢2楼评论我是真没想到这玩意还会有人来评论
2021-3-24 23:19
0
游客
登录 | 注册 方可回帖
返回
//