王爽《汇编语言》(第3版)第16章中断例程实验解决方案

准备知识

这个中断例程的综合性较强,说真的我琢磨了很长时间,几乎考虑到了前面所有章节的知识,最后是用debug调试程序找到了关键问题。

中断例程的空间

该中断例程的功能较多,所以占用的内存有必要考虑下,功能程序写好后进入debug可查看程序长度,大约是180字节。
内存中,一般从0000:0200至0000:02FF的 256 个字节空间是空闲可用的,可以估算出7ch中断例程的长度不可能超过256个字节,故7ch可以安装到0:200处。

标号的重要用法

数据标号

  1. 数据标号可直接用来访问数据
    用伪指令assume将标号所在的段和一个段寄存器联系起来,例如:

assume ds:data

那么data段中的标号的段地址默认在ds中,并不是说ds存放的内容就是data段的段地址。

  1. 数据标号可以当作数据来定义
    例如:

a db 1,2,3,4
b dw 0,0

那么

c dw a,b

c处存放的为a和b的偏移地址

c dd a,b

存放的分别为a的偏移地址和段地址、b的偏移地址和段地址

  1. 用法举例
    mov ax,标号(字单元)
    mov 标号(字节单元),ax
    add 标号,10
    ……

地址标号

地址标号(带“:”)仅表示内存单元的地址,只能在代码段中使用;
可以和数据标号搭配使用。

编译器对标号的处理

数据标号 dw 标号1,标号2

存放标号1、标号2的偏移地址,两种标号都可行。

数据标号[reg + idata]

显式的偏移地址,隐含的段地址在标号所在段相联系的段寄存器中。

  1. 方括号中标号的处理

[reg + 数据标号 - 地址标号 + idata]

均作为偏移地址处理,但默认段地址在ds中,本实验就用到这种形式。

参考实验

运行环境

dosbox0.74

实验要点

实验任务是安装int 7ch中断例程,实现的功能就来源于子程序setscreen,我们很容易写出的安装程序如下图
在这里插入图片描述
这个程序有很大的问题,因为划线处的标号的地址是安装程序的运行地址,而非目标中断例程的运行地址。
我们所写的标号偏移地址是在编译器编译过程中就确定好的,并不会随程序的运行而改变。那么table处直接定址表存放的应该为目标程序入口地址,并且在目标程序中又需要找到直接定址表。
综上,接下来要解决的问题是目标程序如何在直接定址表中取得正确的入口地址。
上图中划线处的标号用到的都是安装程序中的偏移地址,也就是说标号的相对位置(即位移)是确定的,这里我们可以联系前面章节提到过的依据位移进行转移的指令的原理考虑这个问题。
我们的安装程序是将中断例程(目标程序)安装到目标地址空间,目标程序的首部和目标地址空间首地址都确定了。因此,在安装程序中目标程序标号位置的目标偏移地址可以这样确定:

地址位移⇨⇨⇨目标偏移地址
标号地址 - 首标号地址+ 目标首偏移地址(地址变量)

实验程序

;mtf安装程序,7ch中断例程  multifunction 多功能;多功能的
assume cs:code
code segment
start: mov ax,cs
 mov ds,ax
 mov si,offset function
 mov ax,0
 mov es,ax
 mov di,200h
 mov cx,offset functionend - offset function
 cld
 rep movsb
 
 mov ax,0
 mov es,ax
 mov word ptr es:[7ch*4],200h
 mov word ptr es:[7ch*4+2],0

 mov ax,4c00h
 int 21h

 ;功能:为显示输出提供如下功能子程序
 ;(1)清屏;(2)设置前景色;(3)设置背景色;(4)向上滚动一行
 ;参数:ah传递功能号:0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行;对1、2号功能,用al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}
 ;返回值:无
 ;
function: jmp short set   ;目标代码存放在0:200处

    table  dw sub1 - function + 200h,sub2 - function + 200h,sub3 - function + 200h,sub4 - function + 200h ;存放目标程序入口地址

set: push bx

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

 call word ptr cs:[bx + table - function + 200h] ;调用对应的功能子程序,注意这里应加上段前缀“cs:sret: pop bx 
 iret    ;中断返回

;功能子程序1:清屏,0号功能
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 ;sub1 ends

;功能子程序2:设置前景色,1号功能
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 ;sub2 ends

;功能子程序3:设置背景色,2号功能
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 ; sub3 ends

;功能子程序4:向上滚动一行,3号功能
sub4: push cx
 push si
 push di
 push es
 push ds

 mov si,0b800h
 mov es,si
 mov ds,si
 mov si,160  ;ds:si指向第n+1行
 mov di,0   ;es:di指向第n行
 cld
 mov cx,24   ;共复制24行

sub4s: push cx
 mov cx,160
 rep movsb    ;复制
   pop cx
 loop sub4s

 mov cx,80 
 mov si,0
sub4s1: mov byte ptr es:[160*24+si],' '  ;最后一行清空
 add si,2
 loop sub4s1

 pop ds
 pop es
 pop di
 pop si
 pop cx
 ret ;sub4 ends

functionend: nop

code ends
end start

编译运行后就进行功能测试了。

测试程序

在测试之前一定要先把实验程序运行一遍,以安装中断例程,注意不要关闭dosbox,建议整个实验过程不要关闭dosbox
重要事情说三遍:
先要运行实验程序!
先要运行实验程序!
先要运行实验程序!

清屏测试

assume cs:code
code segment
start: mov ah,0  ;测试 0 号功能
 int 7ch   ;调用int7ch中断例程
 mov ax,4c00h
 int 21h
code ends
end start

运行结果
在这里插入图片描述

前景测试

assume cs:code
code segment
start: mov ah,1  ;测试 1 号功能
 mov al,4  ;红色
 int 7ch   ;调用int7ch中断例程
 mov ax,4c00h
 int 21h
code ends
end start

运行结果
在这里插入图片描述

背景测试

assume cs:code
code segment
start: mov ah,2  ;测试 2 号功能
 mov al,1  ;蓝色
 int 7ch   ;调用int7ch中断例程
 mov ax,4c00h
 int 21h
code ends
end start

运行
在这里插入图片描述

向上卷行

assume cs:code
code segment
start: mov ah,3  ;测试 3 号功能
 int 7ch   ;调用int7ch中断例程 
 mov ax,4c00h
 int 21h
code ends
end start

运行
在这里插入图片描述

结束语

以上就是我个人提供的全部解决方案,希望能够帮助到你,如果你认为有帮助,不妨推荐给身边学习汇编的朋友!感谢阅读,加油!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值