王爽书上实验16,安装新中断7ch到0:200处,我不是按200h进行加减,我是用call指令,然后用pop得到ip然后进行加减得到当前入口,奇怪在dos全屏下可以改变字体颜色但无法正确返回,dos窗口卡死
这是调用程序
;--------------------------------------------------------------------------------------------------------
;首先必须先运行后面安装中断程序然后再运行这个调用程序
;1)0号功能清屏,2)1号功能设置前景色,3)2号功能设置背景色,4)3号功能向上滚动1行
assume cs:code
code segment
main:
;按下面运行参数设置
mov ah,1 ;功能号(1-3)
mov al,6 ;颜色值(0-7)
int 7ch
mov ax,4c00h
int 21h
code ends
end main
;这是安装程序
;--------------------------------------------------------------------
;安装1个新的int7ch中断列程,为显示输出提供如下功能:
;1)0号功能清屏,2)1号功能设置前景色,3)2号功能设置背景色,4)3号功能向上滚动1行
;入口参数 1)用ah传递功能号(即选择子程序里功能) 2)对于2、3号功能用al传递颜色值(0-7)
assume cs:code
code segment
main:
;把setint7s安装到0:200h处
mov ax,0
push ax
pop es
mov di,200h
push cs
pop ds
mov si,setint7s
mov cx,setint7e-setint7s
cld
rep movsb
;设置中断表
cli
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
sti
mov ax,4c00h
int 21h
setint7s: ;入口参数ah保存调用功能号,al何存颜色
push cx
call s
cont:
push bp
push si
push es
push di
push ds
push bx
jmp next
s:
pop cx ;得到当前ip
add sp,2 ;sp+2即放弃cs值
sub cx,4 ;cx存放当前程序入口地址(此时cx=200h)
jmp cont
next:
jmp start
table dw offset sub0 -offset setint7s, offset sub1-offset setint7s,offset sub2-offset setint7s,offset sub3 -offset setint7s
start:
mov bx,0b800h
mov es,bx
cmp ah,3
ja exit
mov bl,ah
mov bh,0
add bx,bx ;确定其在table中保存位置
add bx,table -offset setint7s ;定位table位置
add bx,cx
mov bx,cs:[bx] ;得到table里保存各个功能偏移
add bx,cx ;把偏移+起始cx得到各个功能偏移(把偏移转成具体地址)
jmp bx
sub0: ;0号功能清屏
mov bp,0
mov cx,2000
do:
mov word ptr es:[bp],0
add bp,2
loop do
jmp exit
sub1: ;1号功能设置前景色,al存储所显示颜色(前景色是0 1 2位)
mov cx,2000
mov bp,1
mov bl,es:[bp] ;读取当前字符颜色
and bl,11111000b ;只删除当前景色,其它属性不变
or al,bl ;更改前景色
do1:
mov es:[bp],al
add bp,2
loop do1
jmp exit
sub2: ;2号功能设置背景色al存储所显示颜色(背景色是4 5 6位)
mov cl,4
shl al,cl ;左移4位使原先00000110 变成01100000这样
mov bp,1
mov bl,es:[bp] ;读取当前字符颜色
and bl,10001111b ;只删除当背景色,其它属性不变
mov cx,2000
or al,bl ;更改背景色
do2:
mov es:[bp],al
add bp,2
loop do2
jmp exit
sub3: ;3号功能向上滚动1行
mov cx,3840
push es
pop ds
cld
mov di,0
mov si,160
rep movsb
mov cx,80
do3:
mov word ptr es:[di],0
inc di
loop do3
jmp exit
exit:
pop bx
pop ds
pop di
pop es
pop si
pop bp
pop cx
iret
setint7e:nop
code ends
end main
------解决方案--------------------
s:
pop cx ;得到当前ip
add sp,2 ;sp+2即放弃cs值 ** 这里有问题吧,段内 call 不涉及 cs 压栈的,所以导致栈不平衡故返回出错了