汇编语言实验10(王爽 第三版)

1.显示字符串
问题
显示字符串是现实工作中经常要用到的功能,应该编写一个通用的子程序来实现这个功
能。我们应该提供灵活的调用接口,使调用者可以决定显示的位置(行、列)、内容和颜色。
子程序描述
名称:show str
功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
参数:(dh)=行号(取值范围024), (d1)=列号(取值范围079),
(c1)=颜色,dsai指向字符串的首地址
返回:无
应用举例:在屏幕的8行3列,用绿色显示data段中的字符串。
提示
(1)子程序的入口参数是屏幕上的行号和列号,注意在子程序内部要将它们转化为显存中的地址,首先要分析1下屏幕上的行列位置和显存地址的对应关系;
(2)注意保存子程序中用到的相关寄存器:
(3)这个子程序的内部处理和显存的结构密切相关,但是向外提供了与显存结构无关
的接口。通过调用这个子程序,进行字符串的显示时可以不必了解显存的结构,为编程提供了方便。在实验中,注意体会这种设计思想。

assume cs:code
data segment
        db 'welcome to masm!',0
data ends

code segment
start:  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 dx
                push cx
                push si
                mov di,0
                mov bl,dh
                dec bl
                mov al,160
                mul bl
                mov bx,ax
                add dl,dl
                add bl,dl
        mov ax,0b800h
        mov es,ax
        mov al,cl
         s:     mov ch,0
                mov cl,ds:[si]
                jcxz ok
                mov es:[bx+di],cl
                mov es:[bx+di+1],al
        add di,2
        inc si
                loop s
         ok:    pop dx
                pop cx
                pop si
                ret
code ends
end start

2,解决除法溢出的问题
前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数;进行16位除法的时候,用ax存储结果的商,dx存储结果的余数。可是,现在有一个问题,如果结果的商大于al或ax所能存储的最大值,那么将如何?
比如,下而的程序段:

mov bh,1
mov ax,1000
div bh

进行的是8位除法,结果的商为1000,而1000在al中放不下。

mov aX,1000H
mov dx,1
mov bx,1
diV bX

进行的是16位除法,结果的商为11000H,而11000H在ax中存放不下。
我们在用div指令做除法的时候,很可能发生上面的情况:结果的商过大,超出了寄存器所能存储的范围。当CPU执行div等除法指令的时候,如果发生这样的情况,将引发CPU的一个内部错误,这个错误被称为:除法溢出。我们可以通过特殊的程序来处理这个错误,但在这里我们不讨论这个错误的处理,这是后面的课程中要涉及的内容。

assume cs:code,ss:stack

stack segment
        dw 8 dup (0)
stack ends

code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,4240h
        mov dx,00fh
        mov cx,0ah
        call divdw
        mov ax,4c00h
        int 21h

divdw:  push ax
        mov ax,dx
        mov dx,0
        div cx

        mov bx,ax
        pop ax
        div cx
        mov cx,dx
        mov dx,bx
        ret
code ends
end start

3.数值显示
问题
编程,将data段中的数据以十进制的形式显示出来。

data segment
  dw 123,12666,1,8,3, 38
data ends

这些数据在内存中都是二进制信息,标记了数值的大小。要把它们显示到屏幕上,成为我们能够读懂的信息,需要进行信息的转化。比如,数值12666,在机器中存储为二进制信息:001100010111101 oB}31 }AH>,计算机可以理解它。而要在显示器上读到可以理解的数值12666,我们看到的应该是一串字符:"12666"。由于显卡遵循的是ASCII编码,为了让我们能在显示器上看到这串字符,‘占在机器中应以ASCII码的形式存储为:
31H, 32H, 36H, 36H, 36H(字符“0”一“9”对应的ASCII码为30H}39H) o
通过上面的分析可以看到,在概念世界中,有一个抽象的数据12666,它表示了一个数值的大小。在现实世界中它可以有多种表示形式,可以在电子机器中以高低电平(二进制)的形式存储,也可以在纸上、黑板上、屏幕上以人类的语言“12666”来书写。现在,我们面临的问题就是,要将同一抽象的数据,从一种表示形式转化为另一种表示形式。 可见,要将数据用十进制形式显示到屏幕上,要进行两步工作:
(1)将用二进制信息存储的数据转变为十进制形式的字符串;
(2)显示十进制形式的字符串。
第二步我们在本次实验的第一个子程序中己经实现,在这里只要调用一下show str即可。我们来讨论第一步,因为将二进制信息转变为十进制形式的字符串也是经常要用到的功能,我们应该为它编写一个通用的子程序。
子程序描述
名称:dtoc
功能:将word型数据转变为表示一十进制数的字符串,字符串以0为结尾符。
参数:(ax)=word型数据
dsai指向字符串的首地址
返回:无
应用举例:编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出
来。在显示时我们调用本次实验中的第一个子程序show str

assume cs:code

data segment
        db 10 dup (0)
data ends

stack segment
    dw 8 dup(0)
stack ends

code segment
start:  mov ax,42243
    mov bx,data
    mov ds,bx
    mov bx,stack
    mov ss,bx
    mov sp,10h
    mov si,0
    call dtoc

    mov dh,8
        mov dl,3
        mov cl,2
        call show_str
        mov ax,4c00h
        int 21h

dtoc:    push ax
    push bx
    push si
    mov bx,10
    mov si,0
    
  s0:    mov dx,0
    div bx
    add dx,30h
    push dx
    mov cx,ax
    inc si
    inc cx
    loop s0
    
    mov cx,si
    mov si,0
  s1:    pop ds:[si]
    inc si
    loop s1

       pop si
    pop bx
    pop ax
    ret
    

show_str:   push ax
        push dx
                push cx
                push si
                mov di,0
                mov bl,dh
                dec bl
                mov al,160
                mul bl
                mov bx,ax
                add dl,dl
                add bl,dl
        mov ax,0b800h
        mov es,ax
        mov al,cl
         s:     mov ch,0
                mov cl,ds:[si]
                jcxz ok
                mov es:[bx+di],cl
                mov es:[bx+di+1],al
        add di,2
        inc si
                loop s
         ok:    pop si
                pop cx
                pop dx
        pop ax
                ret
code ends
end start

发布日期:

所属分类: 编程 标签:


没有相关文章!