汇编语言 王爽 第二版 实验16

实验16 编写包含多个功能子程序的中断例程


目录

  • 题目要求
  • 代码
    • 错误代码
    • 错误代码分析
    • 正确代码
  • 补充

题目要求

安装一个新的int 7ch中断例程,为显示输出提供如下功能子程序。
(1) 清屏
(2) 设置前景色
(3) 设置背景色
(4) 向下滚动一行

入口参数说明如下:
(1) 用ah寄存器传递功能号:0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行
(2) 对于1、2号功能,用al传送颜色值,(al)∈{ 0,1,2,3,4,5,6,7 }


代码

错误代码:

assume cs:code 
code segment

start:  mov ax,cs
        mov ds,ax
        mov si,offset sscreen

        mov ax,0
        mov es,ax
        mov di,200h

        mov cx,offset sscreenend – offset sscreen
        cld
        rep movsb

        ; 设置7ch号中断的入口地址
        mov word ptr es:[7ch*4],200h
        mov word ptr es:[7ch*4+2],0

        mov ax,4c00h
        int 21h

sscreen:    jmp short s
    table dw sub1, sub2, sub3, sub4

s:      push bx

        cmp ah,3        ; 判断功能号是否大于3
        ja sret
        mov bl,ah
        mov bh,0
        add bx,bx       ; 根据ah中的功能号计算对应子程序
                        ; 在table表中的偏移

        call word ptr table[bx]     ; 调用对应的功能子程序

sret:       pop bx
        iret 

; 清屏子程序
sub1:   push bx
        push cx
        push es

        mov bx,0b800h
        mov es,bx
        mov bx,0
        mov cx,2000
sub1s:  mov byte ptr es:[bx],’ ‘
        add bx,2
        loop sub1s

        pop es
        pop cx
        pop bx
        ret 


; 设置前景色子程序
sub2:   push bx
        push cx
        push es

        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub2s:  and byte ptr es:[bx],11111000B
        or es:[bx],al
        add bx,2
        loop sub2s

        pop es
        pop cx
        pop bx
        ret 

; 设置背景色子程序
sub3:   push bx
        push cx
        push es

        mov cl,4
        shl al,cl
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub3s:  and byte ptr es:[bx],10001111B
        or es:[bx],al
        add bx,2
        loop sub3s

        pop es
        pop cx
        pop bx
        ret

; 向下滚动一行子程序
sub4:   push cx
        push si
        push di
        push es
        push ds

        mov si,0b800h
        mov es,si
        mov ds,si
        mov si,160
        mov di,0
        cld
        mov cs,24

sub4s:  push cx
        mov cx,160
        rep movsb
        pop cx
        loop sub4s

        mov cx,80
        mov si,0
sub4s1: mov byte ptr [160*24+si], ‘ ‘
        add si,2
        loop sub4s1

        pop ds
        pop es
        pop di
        pop si
        pop cx
        ret

sscreenend: nop 
code ends
end start

错误代码分析:

上面的代码会出错,知道错误在哪里吗?怎么改正?
我们的测试程序主要代码为:

mov ax,0    ; 触发7ch号中断的0号清屏子程序
int 7ch 

运行测试程序,跳转不到sub1清屏子程序。用debug进行调试安装安装程序:
当运行到call word ptr table[bx]时,此时地址错误。
这里写图片描述

这里写图片描述

我们查看安装程序的汇编指令,正确的位置应该为:
这里写图片描述

那么究竟是什么原因导致了跳转不到正确的位置?
其实原因很简单,就是table标号表示偏移地址。这个是安装程序,在运行安装程序的时候,它的偏移地址为002A。将table移到7ch中断向量表的入口地址处时,它的值还是002A。此时段地址就为0000H,所以执行call word ptr table[bx]就相当于执行了,call word ptr cs:[002AH]。

那么解决的方法是什么呢?
很简单,在进行指令移植的时候在前面指定偏移地址。使用 org 200H语句,这条语句指定了org 200H后面的指令都会被加载到偏移地址为200H的位置(段地址随便,因为org 200H执行的原因,编译器会将table的偏移位置解析正确了)。我们移植org 200H后面的指令到0:200H的位置。

文章最后面查看知识点补充:org指令。

正确代码:

assume cs:code 
code segment

start:  mov ax,cs
        mov ds,ax
        mov si,offset sscreen

        mov ax,0
        mov es,ax
        mov di,200h

        mov cx,offset sscreenend – offset sscreen
        cld
        rep movsb

        ; 设置7ch号中断的入口地址
        mov word ptr es:[7ch*4],200h
        mov word ptr es:[7ch*4+2],0

        mov ax,4c00h
        int 21h

        org 200h        ; 正确的做法,指定此时的偏移地址为200H
sscreen:    jmp short s
    table dw sub1, sub2, sub3, sub4

s:      push bx

        cmp ah,3        ; 判断功能号是否大于3
        ja sret
        mov bl,ah
        mov bh,0
        add bx,bx       ; 根据ah中的功能号计算对应子程序
                        ; 在table表中的偏移

        call word ptr table[bx]     ; 调用对应的功能子程序

sret:   pop bx
        iret 

; 清屏子程序
sub1:   push bx
        push cx
        push es

        mov bx,0b800h
        mov es,bx
        mov bx,0
        mov cx,2000
sub1s:  mov byte ptr es:[bx],’ ‘
        add bx,2
        loop sub1s

        pop es
        pop cx
        pop bx
        ret 


; 设置前景色子程序
sub2:   push bx
        push cx
        push es

        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub2s:  and byte ptr es:[bx],11111000B
        or es:[bx],al
        add bx,2
        loop sub2s

        pop es
        pop cx
        pop bx
        ret 

; 设置背景色子程序
sub3:   push bx
        push cx
        push es

        mov cl,4
        shl al,cl
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub3s:  and byte ptr es:[bx],10001111B
        or es:[bx],al
        add bx,2
        loop sub3s

        pop es
        pop cx
        pop bx
        ret

; 向下滚动一行子程序
sub4:   push cx
        push si
        push di
        push es
        push ds

        mov si,0b800h
        mov es,si
        mov ds,si
        mov si,160
        mov di,0
        cld
        mov cs,24

sub4s:  push cx
        mov cx,160
        rep movsb
        pop cx
        loop sub4s

        mov cx,80
        mov si,0
sub4s1: mov byte ptr [160*24+si], ‘ ‘
        add si,2
        loop sub4s1

        pop ds
        pop es
        pop di
        pop si
        pop cx
        ret

sscreenend: nop 
code ends
end start

补充

[1] ORG指令
org(origin)指令指定偏移地址。经常使用中断向量表的时候,我们需要指定偏移位置,因为后边的标号是要发生改变的,我们使用org指令就可以产生一个指定的对齐方式。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值