王爽《汇编语言》实验16

时间:2022-06-24 12:57:34

实验结果

王爽《汇编语言》实验16

代码如下

assume cs:code
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
push cs
pop ds
mov ax,0
mov es,ax
mov si,offset int_7CH;ds:[si]指向源地址
mov di,204H;es:[di]指向目的地址
mov cx,offset int_7CHEnd-offset int_7CH;(cx)=传输长度
cld;传输方向为正
rep movsb
push es:[7CH*4]
pop es:[200H]
push es:[7CH*4+2]
pop es:[202H];原中断矢量表中int_7CH地址保存至es:[200H]
mov word ptr es:[7CH*4],204H
mov word ptr es:[7CH*4+2],0;设置中断矢量表
mov ah,2;功能号2,设置背景色
mov al,2;颜色值
int 7CH
push es:[200H]
pop es:[7CH*4]
push es:[202H]
pop es:[7CH*4+2];恢复原本中断矢量表中int 7CH中断例程入口的地址
mov ax,4C00H
int 21H
org 204H;伪指令,表示下一条地址从偏移地址204H开始,和安装后的偏移地址相同,若没有org 204H,中断例程安装后,标号代表的地址改变了,和之前编译器编译的有所区别
;名称:int_7CH
;功能:如下功能子程序:清屏,设置前景色,设置背景色和向上滚动一行,功能号为0~3
;参数:(ah)为功能号
;返回:根据功能号调用相应子程序的返回值
int_7CH:
jmp short int_7CHBegin
table dw sub1,sub2,sub3,sub4
int_7CHBegin:
push bx
cmp ah,3;判断功能号是否大于3
ja int_7CHRet
mov bl,ah
mov bh,0
add bx,bx
call word ptr table[bx];根据功能号计算对应子程序在table表中的偏移
int_7CHRet:
pop bx
iret
sub1:;清屏子程序,功能号为0
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:;设置前景色子程序,功能号为1
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;al传送颜色值,00000000B~00000111B
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret
sub3:;设置背景色子程序,功能号为2
push bx
push cx
push es
mov cl,4
shl al,cl;颜色值左移4位
mov bx,0B800H
mov es,bx
mov bx,1
mov cx,2000
sub3s:
and byte ptr es:[bx],10001111B;改变奇地址
or es:[bx],al;00000000B~01110000B
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;ds:[si]一开始指向第1行
mov di,0;es:[di]一开始指向第0行
cld
mov cx,24;复制24行
sub4s:
push cx
mov cx,160;cx为传送长度
rep movsb;每次操作si和di递增,不需要再设置行号和列数
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
int_7CHEnd:
nop
code ends
end start


很多人在这里会出错,单步中断,发现问题出在call word ptr table[bx]这句。

解决方法很简单,在int_7CH标号前加一句org 204H就够了,204H是安装后的偏移地址。

首先看看不加org 204H会发生什么情况。

在编译生成exe文件后,用debug来查看编译后的情况:

王爽《汇编语言》实验16

发现编译后call word ptr table[bx]实际上是call CS:[BX+005E],也就是0772:[005E+BX],这是编译后table的位置。

但是传输完程序,设置了中断向量表,此时int_7CH被装到了0000:0204,执行int 7CH指令,一直到call word ptr table[bx]:

王爽《汇编语言》实验16

发现call word ptr table[bx]还是call CS:[BX+005E],0772:[005E+BX],还是原来的地址,而不是0000::[BX+0206],即安装新int 7CH后的新地址。

所以这里org 204H的目的实际上是告诉编译器int_7CH的偏移地址是204H,而不是005E。

不写这条指令,中断例程被安装后,标号代表的地址变了,与之前编译器编译的有区别,那到了call指令这里就会出错。