汇编 实现小数乘法,保留有效小数位2位
汇编的小数计算和显示是一个难人的问题
以下2个实现小数乘法的程序
请参考,提修改建议
课本的
title a13calc(exe) ;输入量和速率的ASCII值,确定十进制小数位,转换为二进制,计算乘积,显示ascii
.model small
.386
.stack 64
.data
leftcol equ 28 ;屏幕位置的等价符号
rightcol equ 52
toprow equ 10
botrow equ 14
qtyparam label byte ;键盘输入的量参数表
maxqlen db 6
actqlen db ? ;输入量的长度
qtyfld db 6 dup(?)
ratepar label byte ;键盘输入的速率参数表
maxrlen db 6
actrlen db ?
ratefld db 6 dup(?)
prompt1 db 'Quantity?'
prompt2 db 'Rate?'
prompt3 db 'product='
ascprod db 10 dup(30h)
prompt4 db 'Press any key to continue or esc to quit'
adjust dw ? ;数据项
binprod dw 00
binqty dw 00
binrate dw 00
col db 00
decind db 00
mult10 dw 01
nodecims dw 00
row db 00
shift dw ?
tenwd dw 10
.code
a10main proc far
mov ax,@data
mov ds,ax
mov es,ax
mov ax,3 ;设置显示方式和清屏
int 10h
a20: call q10 ;清除窗口
call b10 ;接受量和速率
call c10 ;把量转换为二进制
call d10 ;把速率转换为二进制
call e10 ;计算乘积,舍入
call f10 ;把乘积转化成ASCII
call g10 ;显示乘积
call h10 ;用户暂停
cmp al,1bh ;按ESC
jne a20
mov ax,4c00h
int 21h
a10main endp
;接受量和速率
b10 proc near
mov row,toprow+1
mov col,leftcol+3
lea bp,prompt1
mov cx,9 ;字符数
call k10 ;显示数据
mov ah,0ah
lea dx,qtyparam
int 21h
mov col,leftcol+3
inc row ;下一行
lea bp,prompt2
mov cx,5
call k10
mov ah,0ah
lea dx,ratepar
int 21h
inc row
ret
b10 endp
;把量转换为二进制
c10 proc near
mov nodecims,00 ;清除十进制小数位的长度
movzx cx,actqlen ;量的长度
lea si,qtyfld-1
add si,cx ;设置量的右进位置
call j10 ;转换成二进制
mov ax,binprod
mov binqty,ax ;存放二进制结果
ret
c10 endp
;把速率转换为二进制
d10 proc near
movzx cx,actrlen ;长度
lea si,ratefld-1
add si,cx ;设置右进位置
call j10 ;转换成二进制
mov ax,binprod
mov binrate,ax ;存放二进制结果
ret
d10 endp
;计算乘积,舍入
e10 proc near
mov cx,10 ;乘积长度
lea di,ascprod
mov al,30h
cld
rep stosb
mov shift,10 ;初始移位因子
mov adjust,00
mov cx,nodecims
cmp cl,6 ;如果大于6位十进制数,出错
ja e40
sub cx,02
jle e30 ;如果小数位多于2位,设为2
mov nodecims,02
mov ax,01
e20: imul ax,10 ;移位因子
loop e20
mov shift,ax
shr ax,1 ;舍入值=移位的一半
mov adjust,ax
e30: mov ax,binqty
mul binrate ;量*速率=乘积
add ax,adjust
adc dx,00
cmp dx,shift ;
jb e50
e40: xor ax,ax ;乘积溢出,清除ax,退出
jmp e70
e50: cmp adjust,00 ;移位
jz e80
div shift
e70: xor dx,dx ;清除余数
e80: ret
e10 endp
;把乘积转化成ASCII
f10 proc near
lea si,ascprod+7
mov byte ptr[si],'.' ;在ASCII乘积设置十进制小数点
add si,nodecims ;设置右边起点
f30: cmp byte ptr[si],'.'
jne f40
dec si
f40: cmp dx,00
jnz f50
cmp ax,0010
jb f60
f50: div tenwd
or dl,30h
mov [si],dl
dec si
sub dx,dx ;清除余数
jmp f30
f60: or al,30h
mov [si],al
ret
f10 endp
;显示乘积
g10 proc near
mov col,leftcol+3
mov cx,09 ;ascprod的长度
lea si,ascprod
g20: cmp byte ptr[si],30h
jne g30
mov byte ptr[si],20h ;在ascprod中前导零,成空白
inc si
loop g20
g30: lea bp,prompt3
mov cx,18
call k10 ;显示乘积提示符
ret
g10 endp
;用户暂停
h10 proc near
mov col,20 ;设置光标位置
mov row,22
lea bp,prompt4
mov cx,40
call k10 ;提示符
mov ah,10h ;键盘输入,退出
int 16h
ret
h10 endp
;把ASCII量和速率转换成二进制在入口处
j10 proc near
mov mult10,0001 ;初始化
mov binprod,00
mov decind,00
xor bx,bx
j20: mov al,[si]
cmp al,'.' ;取ASCII字符十进制小数点
jne j30
mov decind,01
jmp j40
j30: and ax,000fh
mul mult10
add binprod,ax
mov ax,mult10
imul ax,10
mov mult10,ax
cmp decind,00
jnz j40
inc bx
j40: dec si
loop j20
cmp decind,00
jz j90
add nodecims,bx
j90: ret
j10 endp
;显示字符, 设置属性
k10 proc near
mov ax,1301h
mov bx,0016h
mov dh,row
mov dl,col
int 10h
ret
k10 endp
;清除窗口
q10 proc near
mov ax,0605h
mov bh,16h
mov ch,toprow ;ch顶行
mov cl,leftcol ;cl左列
mov dh,botrow ;dh底行
mov dl,rightcol ;dl右列
int 10h
ret
q10 endp
end a10main