论坛首页· 友情链接申请·申请版主· 广告投放· 道具中心· 设为首页· 收藏本站
发新话题
打印

汇编 实现小数乘法,保留有效小数位2位

汇编 实现小数乘法,保留有效小数位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
自学难成才,我们需要集体的力量 自学成才的是天才,但也希望你们的智慧与人共享

TOP

觉得课本的那道有许多的限制
如:单个输入值超过65535则溢出,乘积dx不存超过1位
即乘积不能超过655360
输入400和400与输入400.0和400.0结果不同

自己修改的程序
title        a13calc(exe)        ;输入sum1和sum2的ASCII值,确定十进制小数位,转换为二进制,计算乘积,显示ascii
.model small
.386
.stack 64
.data

;输入参数表
mes1                db        'sum1=$'
mes2         db        0dh,0ah
                db        'sum2=$'
result        db        0dh,0ah
                db        'result=$'
ascprod        db         11 dup(30h),'$'
sum1                label        byte        ;键盘输入的量参数表
maxlen1        db        5
actlen1        db        ?                ;输入量的长度
sum1fld        db        5 dup(?)
sum2                label        byte        ;键盘输入的速率参数表
maxlen2        db        5
actlen2        db        ?
sum2fld         db        5 dup(?)


;数据项                       
binprod        dw        00                ;暂存转化的二进制值
binsum1        dw        00                ;sum1的二进制值
binsum2        dw        00                ;sum2的二进制值
decind        db        00                ;小数点标志
mult10        dw        01                ;乘积因子
nodecims        dw        00                ;整体小数位数
shift        dw        ?                ;移位倍数
adjust        dw        ?                ;折半       

.code
a10main        proc far
        mov ax,@data
        mov ds,ax
        mov es,ax
        mov dx,offset mes1
        mov ah,9
        int 21h
        mov dx,offset sum1
        mov ah,0ah
        int 21h
        mov dx,offset mes2
        mov ah,9
        int 21h
        mov dx,offset sum2
        mov ah,0ah
        int 21h
       
        call c10                        ;把sum1转换为二进制
        call d10                        ;把sum2转换为二进制
        call e10                        ;计算乘积,舍入
        call f10                        ;把乘积转化成ASCII
        call g10                        ;显示乘积
        mov ax,4c00h
        int 21h
a10main endp

;把sum1转换为二进制
c10 proc near
        mov nodecims,00                ;清除十进制小数位的长度
        movzx cx,actlen1                ;sum1的长度 数据传送扩展指令movzx 源操作数<=目的操作数长度
        lea si,sum1fld-1               
        add si,cx                                ;设置sum1的右进位置,si指向最低位
        call j10                                ;转换成二进制
        mov ax,binprod                       
        mov binsum1,ax                        ;存放二进制结果
        ret
c10 endp

;把sum2转换为二进制
d10 proc near
        movzx cx,actlen2                ;长度
        lea si,sum2fld-1
        add si,cx                                ;设置右进位置
        call j10                                ;转换成二进制
        mov ax,binprod                       
        mov binsum2,ax                        ;存放二进制结果
        ret
d10 endp

;计算乘积,舍入
e10 proc near
        mov cx,11                                ;乘积长度
        lea di,ascprod
        mov al,30h
        cld
        rep stosb
        mov shift,10                        ;初始移位因子
        mov adjust,00
        mov cx,nodecims                ;小数位数
        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,binsum1
        mul binsum2                        ;sum1*sum2=乘积
        add ax,adjust
        adc dx,00       
        cmp adjust,00                        ;移位
        jz e40
        push ax
        mov ax,dx
        mov dx,0
        div shift
        mov bx,ax
        pop ax
        div shift
        ;mov cx,dx
        mov dx,bx
e40:        ret
e10 endp

;把乘积转化成ASCII
f10        proc near
        lea si,ascprod+8
        mov byte ptr[si],'.'        ;在ASCII乘积设置十进制小数点
        add si,nodecims                ;设置右边起点
f20:        cmp byte ptr[si],'.'               
        jne f30
        dec si       
f30:        cmp dx,0
        je f40                        ;当乘积中dx为0转f40
        push ax                        ;当乘积超16,防止除法溢出
        mov ax,dx                        ;被除数DX AX
        mov dx,0                        ;  除数CX                       
        mov cx,10                        ;    商DX AX
        div cx                        ;  余数CX
        mov bx,ax
        pop ax
        div cx
        mov cx,dx
        mov dx,bx
        or cl,30h
        mov [si],cl
        dec si
        jmp f20       
f40:        cmp ax,10                        ;当dx=0用循环除十求余
        jb f50
        mov cx,10
        div cx
        or dl,30h
        mov [si],dl
        dec si
        mov dx,0
        jmp f20
f50: or al,30h
        mov [si],al
        ret
f10        endp

;显示乘积
g10 proc near
        mov cx,10                                ;ascprod的长度
        lea si,ascprod
g20:        cmp byte ptr[si],30h
        jne g30
        mov byte ptr[si],20h        ;在ascprod中前导零,成空白
        inc si
        loop g20
g30:       
        mov ah,9
        mov dx,offset result       
        int 21h                                ;显示乘积提示符
        mov dx,offset ascprod
        int 21h
        ret
g10 endp

;把ASCIIsum1和sum2转换成二进制在入口处
j10        proc near
        mov mult10,0001                ;初始化
        mov binprod,00                       
        mov decind,00
        xor bx,bx               
j20:        mov al,[si]                        ;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                ;存储2个数的小数总位数
j90:        ret
j10        endp

end a10main
自学难成才,我们需要集体的力量 自学成才的是天才,但也希望你们的智慧与人共享

TOP

虽然修改的程序只能输入最多4位数
但其他的溢出问题都已经解决
有不足请指出

希望有更简单,更全面的小数运算程序
参考
自学难成才,我们需要集体的力量 自学成才的是天才,但也希望你们的智慧与人共享

TOP

顶一下

好文都要顶一下的。
SEO服务博客有着很多关于优化的资料

TOP

感觉很麻烦啊 不过很有魅力

TOP

!

!!!!!!!!!!!!!!!!!!

TOP

发新话题