王爽-实验十

王爽-实验十

一.显示字符串

1.实验要求

在这里插入图片描述

2.程序代码:

;编写show_str子程序,指定位置和颜色,显示一个用0结尾的字符串
;dh显示行号,dl显示列号
;cl显示颜色
assume cs:code,ds:data,ss:stack
data segment
    db 'Welcome to masm!',0
data ends
stack segment
    db 16 dup(0)
stack ends
code segment
start:      mov ax,stack
            mov ss,ax
            mov sp,16

            mov dh,8
            mov dl,3
            mov cl,2
            mov ax,data
            mov ds,ax
            mov si,0
            call show_str

            mov ax,4c00h
            int 21h

show_str:   push ax
            push bx
            push cx
            push dx
            push di
            push si
            
            mov ax,0b800h
            mov es,ax

            ;ax现在没有使用到
            mov al,dh
            mov dh,160
            mul dh
            ;现在ax存放的是结果
            mov dh,0
            add ax,dx
            inc ax
            ;现在ax存放的是要存放字符的位置
            mov bx,ax
            mov di,0
            mov al,cl
            ;di索引的是数据段
            ;si索引的是显存段
            ;al放属性,cx自由了
            ;bx为基址
            ;开始放字符
    show:   mov cl,[di]
            mov ch,0
            jcxz ok
            mov es:[bx+si],cl
            mov es:[bx+si+1],al
            inc di
            add si,2
            jmp short show

            ;函数返回
    ok:     pop si 
            pop di
            pop dx
            pop cx
            pop bx
            pop ax
            ret

code ends
end start

3.实验结果:

在这里插入图片描述

4.错误点:

没有注意到要显示字符串在显存中的放置顺序是:字符,属性,字符属性…,只将基址定位到了第8行的第四个位置,实际上第四个位置是第二个字符的属性,因此设置基址应该+1

二.解决除法溢出的问题

1.实验要求

在这里插入图片描述
公式:
在这里插入图片描述

2.分析过程

(1).首先计算int(H/N)
首先要进行除法,ax中要存放被除数,第一步要计算的是高16位的除法,所以低16位得暂存,因此有:

mov si,ax;

因为除数为16位,因此被除数需要在高16位设置为0,低16位设置为输入的高16位,即H,之后做除法,因此有:

		mov ax,dx;这里低16位设置为原来的高16位,而高16位设置为0
        mov dx,0
        div cx;现在商在ax,余数在dx

除法结束之后,ax中存放这次除法的商,即int(H/N),dx中存放这次除法的余数,即rem(H/N),因为接下来还要进行除法运算,所以要保存ax中的值,而dx中的值下面还要用到,所以在进行第二步之前要保存ax

mov di,ax

*(2).[rem(H/N)65536+L]/N
首先是rem(H/N)*65536,这不计算实际上就是将前一步结果的余数左移16位,也即放在高16位的地方,刚好他在dx中,所以不同动他,后面加上L,也即原来输入的低16位,将他放回ax中就好,之后进行除法

mov ax,si
div cx

除法结束:现在余数在dx中,商在ax中,这里ax就是最后结果的低16位,而结果的高16位就在前面存放的di中,因为公式中是int(H/N)*65536,就是将第一步运算的商左移16位,即放在高16位中,因此只需将其放在dx中就好。

        mov cx,dx
        mov dx,di

3.程序代码

;实验10-2解决除法溢出的问题
assume cs:code,ss:stack
stack segment
    db 16 dup(0)
stack ends
code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16

        mov ax,4240h;低16位
        mov dx,000fh;高16位
        mov cx,0ah;除数
        call divdw

        mov ax,4c00h
        int 21h

;子程序:解决除法溢出
;实现公式: X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N
;输入:使用ax放低16位,dx放高16位
;使用cx放除数
;输入:使用ax放低16位,dx放高16位
;使用cx放余数
;
divdw:  mov si,ax;暂时存放低16位
        mov ax,dx;这里低16位设置为原来的高16位,而高16位设置为0
        mov dx,0
        div cx;现在商在ax,余数在dx
        ;因为要左移16位,所以商应该放在高16位中
        ;先暂存商
        mov di,ax
        ;现在计算+后面的
        ;前面运算之后余数在dx中,也就是说rem(H/N)的结果在dx中
        ;dx刚好是存放高16位的地方,所以不用理
        ;+L就把原来输入的时候的低16位放在ax中就好了
        mov ax,si
        div cx
        ;除法结束:现在余数在dx中,商在ax中,这里ax就是最后结果的低16位
        mov cx,dx
        mov dx,di
        
        ret 

code ends
end start
        

4.实验结果

在这里插入图片描述

三.数值显示

1.实验要求

在这里插入图片描述

2.实验分析

1.做除法,将余数压入栈中,将商作为下次除法的被除数,并且将商传入cx中使得上为0时跳出
注意:
1.这一步需要在开始压0入栈中,作为结束标志
在这里插入图片描述

2.记得将余数加上30h转换为ASCII码

dtoc:       mov bx,10;bx为除数
            mov dx,0;高16位设置为0,因为除数是16位的
            mov si,0;si作为后面的数据段的索引
            push si;压一个0为结束符
    begin:  mov dx,0;高16位要清理,因为进行一次除法运算之后存放余数
            div bx
            mov cx,ax;使用商作为判断条件
            add dx,30h;转换为ASCII码
            push dx;余数压入栈中
            jcxz ojbk

            jmp short begin

2.弹出栈,并且将值放入data段中

   ojbk:   pop cx
            jcxz okk
            mov [si],cl
            inc si
            jmp short ojbk

    okk:    ret

3.程序代码

;数值显示:将data中的数据转换为ASCII码,
;之后调用show_str将其显示在屏幕上
assume cs:code,ds:data,ss:stack
data segment
    db 10 dup(0)
data ends

stack segment
    db 16 dup(0)
stack ends

code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16

        mov ax,12666
        mov bx,data
        mov ds,bx
        call dtoc

        mov dh,8
        mov dl,3
        mov cl,2
        mov si,0
        call show_str

        mov ax,4c00h
        int 21h

show_str:   push ax
            push bx
            push cx
            push dx
            push di
            push si
            
            mov ax,0b800h
            mov es,ax

            ;ax现在没有使用到
            mov al,dh
            mov dh,160
            mul dh
            ;现在ax存放的是结果
            mov dh,0
            add ax,dx
            inc ax
            ;现在ax存放的是要存放字符的位置
            mov bx,ax
            mov di,0
            mov al,cl
            ;di索引的是数据段
            ;si索引的是显存段
            ;al放属性,cx自由了
            ;bx为基址
            ;开始放字符
    show:   mov cl,[di]
            mov ch,0
            jcxz ok
            mov es:[bx+si],cl
            mov es:[bx+si+1],al
            inc di
            add si,2
            jmp short show

            ;函数返回
    ok:     pop si 
            pop di
            pop dx
            pop cx
            pop bx
            pop ax
            ret

;子函数转换数字为ASCII码
;ax为输入,结果放在ds段中
;不能放栈中,栈只能存放一个16位的数据
dtoc:       mov bx,10;bx为除数
            mov dx,0;高16位设置为0,因为除数是16位的
            mov si,0;si作为后面的数据段的索引
            push si;压一个0为结束符
    begin:  mov dx,0;高16位要清理,因为进行一次除法运算之后存放余数
            div bx
            mov cx,ax;使用商作为判断条件
            add dx,30h;转换为ASCII码
            push dx;余数压入栈中
            jcxz ojbk

            jmp short begin

    ojbk:   pop cx
            jcxz okk
            mov [si],cl
            inc si
            jmp short ojbk

    okk:    ret

code ends
end start


4.实验结果

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值