编程:安装一个新的int7ch中断例程,为显示输出提供以下功能子程序
(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
stack segment
db 128 dup (0)
stack ends
code segment
start:push cs
pop ds ;这里赋值只是用来复制代码块
mov si, offset int7c
mov ax, 0
mov es, ax
mov di, 204h
mov cx, offset int7cend - offset int7c
cld
rep movsb
;保存原有int 9号中断处理程序的入口地址
push es:[7ch*4]
pop es:[200h]
push es:[7ch*4+2]
pop es:[202h]
;设置中断向量表
cli
mov word ptr es:[7ch*4], 204h
mov word ptr es:[7ch*4+2], 0
sti
;调用
mov al, 1
mov ah, 0
int 7ch
mov ax, 4c00h
int 21h
;-----------新的int 7c中断例程-------------
int7c: jmp short set
table dw cls, frontColor, backColor, scroll
set: push bx
cmp ah, 3
ja int7cret
mov bl, ah
mov bh, 0
add bx, bx
call word ptr table[bx]
int7cret: pop bx
iret
;-----------清屏----------------
cls: push bx
push cx
push es
mov bx, 0b800h
mov es, bx
mov di, 0
mov cx, 2000
s1: mov byte ptr es:[di], ' '
add di, 2
loop s1
pop es
pop cx
pop bx
ret
;-----------设置前景色----------------
frontColor:
push bx
push cx
push es
mov bx, 0b800h
mov es, bx
mov bx, 1
mov cx, 2000
s2: and byte ptr es:[bx], 11111000B
or es:[bx], al
add bx, 2
loop s2
pop es
pop cx
pop bx
ret
;-----------设置背景色----------------
backColor:
push bx
push cx
push es
mov cl, 4
shl al, cl
mov bx, 0b800h
mov es, bx
mov bx, 1
mov cx, 2000
s3: and byte ptr es:[bx], 10001111B
or es:[bx], al
add bx, 2
loop s3
pop es
pop cx
pop bx
ret
;-----------滚动一行----------------
scroll: push cx
push es
push ds
push si
push di
mov si, 0b800h
mov es, si
mov di, 0h
mov ds, si
mov si, 160
mov cx, 24
cld
s4: push cx
mov cx, 160
s5: rep movsb
pop cx
loop s4
mov cx, 80
mov di, 0
s6: mov byte ptr es:[160*24 + di], ' '
add di, 2
loop s6
pop di
pop si
pop ds
pop es
pop cx
ret
int7cend:nop
code ends
end start
程序编译运行后发现未按照预期执行,查看标号中的地址如图
原来,程序在编译的时候编译器已经计算好了标号的地址为图中所示:005F,007A,0098,00BA,新的中断例程在装载的时候重置了cs和ip的值,但是标号的偏移地址发生了改变,因此指向了错误的位置。我们可以利用伪指令org来通知编译器重新计算标号的地址,改动如下:
重置一下标号的地址
可以看到,此时标号处的地址正确显示了,还有一种改法如下:
table dw cls - int7c + 204H,frontColor - int7c + 204H,backColor - int7c + 204H,scroll - int7c + 204H
其实两种做法都是基于同一原理,都是重新计算偏移地址