鱼C论坛

 找回密码
 立即注册
查看: 2585|回复: 11

int 9 中断例程

[复制链接]
发表于 2017-2-7 18:37:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。
;在显示的过程中,按下“ESC”键后,改变显示的颜色。 
assume cs:code,ss:stack,ds:data

data segment
                        db 0,0,0,0
data ends

stack segment
                        db 128 dup(0)
stack ends

code segment
start:                 mov ax,data
                        mov ds,ax
                        mov ax,stack
                        mov ss,ax
                        mov sp,128
                        mov ax,0
                        mov es,ax                        ;中断向量表的段地址为0
                
                        push es:[9*4]                ;将原来 int 9 中断例程的指令的                        
                        pop ds:[0]                        ;ip保存到ds:[0],cs保存到ds:[2]单元中
                        push es:[9*4+2]
                        pop ds:[2]
                        
                        mov word ptr es:[9*4],offset int9
                        mov word ptr es:[9*4+2],cs        ;设置新的中断例程
                        
                        
                        mov ax,0b800h
                        mov es,ax
                        mov si,160*12+40*2
                        mov ah,'a'
                        
s:                        mov es:[si],ah
                        call delay        
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push ds:[0]                        
                        pop es:[9*4]
                        push ds:[2]
                        pop es:[9*4+2]

                        mov ax,4c00h
                        int 21h
                        
delay:          push ax
                        push dx
                        
                        mov dx,1000h
                        mov ax,0
                        
s1:                        sub ax,1
                        sbb dx,0
                        cmp ax,0
                        jne s1
                        cmp dx,0ff0h
                        jne s1
                        
                        pop dx
                        pop ax
                        ret
;--------以下为新的 int 9 中断例程--------------------

int9:                push ax
                        push bx
                        push es
                        push si
                        
                        in al,60h                ;从60h端口读入数据
                        
                        pushf
                        pop bx
                        pushf
                        and bx,1111110011111111b
                        push bx
                        popf
                        call dword ptr ds:[0]        ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:[si+1]         ;属性增加1,改变颜色

int9ret:        pop si
                        pop es
                        pop bx
                        pop ax
                        iret
                         
code ends

end start

如图,程序在 mov word ptr [9*4],0ffset int9 位置处发生了错误,此后无法执行任何内容,呈死机状态。
QQ截图20170207183100.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-2-7 22:25:33 | 显示全部楼层
1.不要用debug单步调试,我复制书上的答案也不能用debug单步调试

2.程序延时太短
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。
;在显示的过程中,按下“ESC”键后,改变显示的颜色。 
assume cs:code,ss:stack,ds:data

data segment
                        db 0,0,0,0
data ends

stack segment
                        db 128 dup(0)
stack ends

code segment
start:                 mov ax,data
                        mov ds,ax
                        mov ax,stack
                        mov ss,ax
                        mov sp,128
                        mov ax,0
                        mov es,ax                        ;中断向量表的段地址为0
                
                        push es:[9*4]                ;将原来 int 9 中断例程的指令的                        
                        pop ds:[0]                        ;ip保存到ds:[0],cs保存到ds:[2]单元中
                        push es:[9*4+2]
                        pop ds:[2]
                        
                        mov word ptr es:[9*4],offset int9
                        mov word ptr es:[9*4+2],cs        ;设置新的中断例程
                        
                        
                        mov ax,0b800h
                        mov es,ax
                        mov si,160*12+40*2
                        mov ah,'a'
                        
s:                        mov es:[si],ah
                        call delay        
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push ds:[0]                        
                        pop es:[9*4]
                        push ds:[2]
                        pop es:[9*4+2]

                        mov ax,4c00h
                        int 21h
                        
delay:          push ax
                        push dx
                        
                        mov dx,1000h
                        mov ax,0
                        
s1:                        sub ax,1
                        sbb dx,0
                        cmp ax,0
                        jne s1
                        ;cmp dx,0ff0h
                        cmp dx,0
                        jne s1
                        
                        pop dx
                        pop ax
                        ret
;--------以下为新的 int 9 中断例程--------------------

int9:                push ax
                        push bx
                        push es
                        push si
                        
                        in al,60h                ;从60h端口读入数据
                        
                        pushf
                        pop bx
                        pushf
                        and bx,1111110011111111b
                        push bx
                        popf
                        call dword ptr ds:[0]        ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:[si+1]         ;属性增加1,改变颜色

int9ret:        pop si
                        pop es
                        pop bx
                        pop ax
                        iret
                         
code ends

end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-8 11:40:32 | 显示全部楼层
人造人 发表于 2017-2-7 22:25
1.不要用debug单步调试,我复制书上的答案也不能用debug单步调试

2.程序延时太短

那程序万一出错了,不能单步调试,看源程序又看不出来,那怎么办啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-8 11:43:26 | 显示全部楼层
Cy86183570 发表于 2017-2-8 11:40
那程序万一出错了,不能单步调试,看源程序又看不出来,那怎么办啊

这个我也没有什么好的办法,因为这个程序比较特殊,此程序正好使用了键盘中断
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-8 12:58:55 | 显示全部楼层
人造人 发表于 2017-2-8 11:43
这个我也没有什么好的办法,因为这个程序比较特殊,此程序正好使用了键盘中断

正头疼中,好像程序无法装入中断向量表中,调试也没办法调试,看程序又没什么问题,汇编可真是麻烦啊!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-8 13:25:37 | 显示全部楼层
Cy86183570 发表于 2017-2-8 12:58
正头疼中,好像程序无法装入中断向量表中,调试也没办法调试,看程序又没什么问题,汇编可真是麻烦啊!

你这个程序没有什么问题呀
就是延时有点少
试试这个
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。
;在显示的过程中,按下“ESC”键后,改变显示的颜色。 
assume cs:code,ss:stack,ds:data

data segment
                        db 0,0,0,0
data ends

stack segment
                        db 128 dup(0)
stack ends

code segment
start:                 mov ax,data
                        mov ds,ax
                        mov ax,stack
                        mov ss,ax
                        mov sp,128
                        mov ax,0
                        mov es,ax                        ;中断向量表的段地址为0
                
                        push es:[9*4]                ;将原来 int 9 中断例程的指令的                        
                        pop ds:[0]                        ;ip保存到ds:[0],cs保存到ds:[2]单元中
                        push es:[9*4+2]
                        pop ds:[2]
                        
                        mov word ptr es:[9*4],offset int9
                        mov word ptr es:[9*4+2],cs        ;设置新的中断例程
                        
                        
                        mov ax,0b800h
                        mov es,ax
                        mov si,160*12+40*2
                        mov ah,'a'
                        
s:                        mov es:[si],ah
                        call delay        
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push ds:[0]                        
                        pop es:[9*4]
                        push ds:[2]
                        pop es:[9*4+2]

                        mov ax,4c00h
                        int 21h
                        
delay:          push ax
                        push dx
                        
                        mov dx,1000h
                        mov ax,0
                        
s1:                        sub ax,1
                        sbb dx,0
                        cmp ax,0
                        jne s1
                        ;cmp dx,0ff0h
                        cmp dx,0
                        jne s1
                        
                        pop dx
                        pop ax
                        ret
;--------以下为新的 int 9 中断例程--------------------

int9:                push ax
                        push bx
                        push es
                        push si
                        
                        in al,60h                ;从60h端口读入数据
                        
                        pushf
                        pop bx
                        pushf
                        and bx,1111110011111111b
                        push bx
                        popf
                        call dword ptr ds:[0]        ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:[si+1]         ;属性增加1,改变颜色

int9ret:        pop si
                        pop es
                        pop bx
                        pop ax
                        iret
                         
code ends

end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-8 13:49:36 | 显示全部楼层
人造人 发表于 2017-2-8 13:25
你这个程序没有什么问题呀
就是延时有点少
试试这个

程序可以运行的,可是我把int 9中断例程的存放位置更改了,就运行不了了,大神,帮我看看
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。
;在显示的过程中,按下“ESC”键后,改变显示的颜色。 
assume cs:code,ss:stack,ds:data

data segment
                        db 0,0,0,0
data ends

stack segment
                        db 128 dup(0)
stack ends

code segment
start:                 mov ax,stack
                        mov ss,ax
                        mov sp,128
                        mov ax,0
                        mov es,ax                        ;中断向量表的段地址为0
                
                        push es:[9*4]                ;将原来 int 9 中断例程的指令的                        
                        pop es:[200h]
                        push es:[9*4+2]                ;ip保存到0:200,cs保存到0:202
                        pop es:[202h]
                        
                        mov ax,cs                        ;将新int 9中断例程的入口地址
                        mov ds,ax
                        mov si,offset int9
                        mov di,204h
                        mov cx,offset int9end - offset int9
                        
                        cld
                        rep movsb                                                
                        
                        cli                                ;将IF置0,屏蔽其他可屏蔽的中断
                        mov word ptr es:[9*4],204h                        ;设置新的中断例程
                        mov word ptr es:[9*4+2],0
                        sti                                ;恢复IF置1
                        
                        mov ax,0b800h
                        mov es,ax
                        mov ah,'a'
                        
s:                        mov es:[160*12+40*2],ah
                        call delay        
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push es:[200h]                        
                        pop es:[9*4]
                        push es:[202h]
                        pop es:[9*4+2]

                        mov ax,4c00h
                        int 21h
                        
delay:          push ax
                        push dx
                        
                        mov dx,1000h
                        mov ax,0
                        
s1:                        sub ax,1
                        sbb dx,0
                        cmp ax,0
                        jne s1
                        cmp dx,0ff0h
                        jne s1
                        
                        pop dx
                        pop ax
                        ret
;--------以下为新的 int 9 中断例程--------------------

int9:                push ax
                        push bx
                        push es
                        
                        in al,60h                ;从60h端口读入数据
                        
                        pushf
                        pop bx
                        pushf
                        and bx,1111110011111111b
                        push bx
                        popf
                        call dword ptr es:[200h]        ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1+80h
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:[160*12+40*2+1]         ;属性增加1,改变颜色

int9ret:        pop es
                        pop bx
                        pop ax
                        iret
int9end:        nop         
code ends

end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-8 14:25:17 | 显示全部楼层
Cy86183570 发表于 2017-2-8 13:49
程序可以运行的,可是我把int 9中断例程的存放位置更改了,就运行不了了,大神,帮我看看
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。
;在显示的过程中,按下“ESC”键后,改变显示的颜色。 
assume cs:code,ss:stack,ds:data

data segment
                        db 0,0,0,0
data ends

stack segment
                        db 128 dup(0)
stack ends

code segment
start:                 mov ax,stack
                        mov ss,ax
                        mov sp,128
                        mov ax,0
                        mov es,ax                        ;中断向量表的段地址为0
                
                        push es:[9*4]                ;将原来 int 9 中断例程的指令的                        
                        pop es:[200h]
                        push es:[9*4+2]                ;ip保存到0:200,cs保存到0:202
                        pop es:[202h]
                        
                        mov ax,cs                        ;将新int 9中断例程的入口地址
                        mov ds,ax
                        mov si,offset int9
                        mov di,204h
                        mov cx,offset int9end - offset int9
                        
                        cld
                        rep movsb                                                
                        
                        cli                                ;将IF置0,屏蔽其他可屏蔽的中断
                        mov word ptr es:[9*4],204h                        ;设置新的中断例程
                        mov word ptr es:[9*4+2],0
                        sti                                ;恢复IF置1
                        
                        mov ax,0b800h
                        mov es,ax
                        mov ah,'a'
                        
s:                        mov es:[160*12+40*2],ah
                        call delay        
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push es:[200h]                        
                        pop es:[9*4]
                        push es:[202h]
                        pop es:[9*4+2]

                        mov ax,4c00h
                        int 21h
                        
delay:          push ax
                        push dx
                        
                        mov dx,1000h
                        mov ax,0
                        
s1:                        sub ax,1
                        sbb dx,0
                        cmp ax,0
                        jne s1
                        ;cmp dx,0ff0h
                        cmp dx, 0 ; 都说了,你的延时太短
                        jne s1
                        
                        pop dx
                        pop ax
                        ret
;--------以下为新的 int 9 中断例程--------------------

int9:                push ax
                        push bx
                        push es
                        
                        ;这里
                        mov ax, 0
                        mov es, ax
                        
                        in al,60h                ;从60h端口读入数据
                        
                        pushf
                        ;pop bx
                        pushf
                        pop bx ;这里
                        and bx,1111110011111111b
                        push bx
                        popf
                        

                        call dword ptr es:[200h]        ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1+80h 
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:[160*12+40*2+1]         ;属性增加1,改变颜色

int9ret:        pop es
                        pop bx
                        pop ax
                        iret
int9end:        nop         
code ends

end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-8 14:44:13 | 显示全部楼层

后来我明白不是程序的问题,你说延时短,真没有问题,我不知道我电脑怎么回事,原来我设置的延时是跟视频里一样很长的,可惜只怪我电脑反映不过来,所以才设置短的,之后都没有问题,直到我改了int 9 中断例程的存储位置,也就是放到了0:204单元才显示不出来,我之后又重看了遍视频,寻找了一些以前别人的程序,才知道不是程序的问题,是必须在DOS实装模式下才能显示出来。抱歉了,费那么大劲,都是我自己没仔细看视频的锅。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-8 15:38:34 | 显示全部楼层
Cy86183570 发表于 2017-2-8 14:44
后来我明白不是程序的问题,你说延时短,真没有问题,我不知道我电脑怎么回事,原来我设置的延时是跟视频 ...

实模式?
下面gif如何解释
GIF.gif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-8 16:07:34 | 显示全部楼层
人造人 发表于 2017-2-8 15:38
实模式?
下面gif如何解释

不是啦,没改int 9程序的存储地址,我也能显示出来的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-8 17:15:40 | 显示全部楼层
Cy86183570 发表于 2017-2-8 16:07
不是啦,没改int 9程序的存储地址,我也能显示出来的

不明白你在说什么,不过问题解决了进行
^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-6 14:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表