Cy86183570 发表于 2017-2-7 18:37:44

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

                        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:        ;对int指令进行模拟,调用原来的int 9中断例程
                       
                        cmp al,1
                        jne int9ret
                       
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:         ;属性增加1,改变颜色

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

end start

如图,程序在 mov word ptr ,0ffset int9 位置处发生了错误,此后无法执行任何内容,呈死机状态。

人造人 发表于 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:                ;将原来 int 9 中断例程的指令的                        
                        pop ds:                        ;ip保存到ds:,cs保存到ds:单元中
                        push es:
                        pop ds:
                        
                        mov word ptr es:,offset int9
                        mov word ptr es:,cs      ;设置新的中断例程
                        
                        
                        mov ax,0b800h
                        mov es,ax
                        mov si,160*12+40*2
                        mov ah,'a'
                        
s:                        mov es:,ah
                        call delay      
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push ds:                        
                        pop es:
                        push ds:
                        pop es:

                        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:      ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:         ;属性增加1,改变颜色

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

end start

Cy86183570 发表于 2017-2-8 11:40:32

人造人 发表于 2017-2-7 22:25
1.不要用debug单步调试,我复制书上的答案也不能用debug单步调试

2.程序延时太短

那程序万一出错了,不能单步调试,看源程序又看不出来,那怎么办啊

人造人 发表于 2017-2-8 11:43:26

Cy86183570 发表于 2017-2-8 11:40
那程序万一出错了,不能单步调试,看源程序又看不出来,那怎么办啊

这个我也没有什么好的办法,因为这个程序比较特殊,此程序正好使用了键盘中断

Cy86183570 发表于 2017-2-8 12:58:55

人造人 发表于 2017-2-8 11:43
这个我也没有什么好的办法,因为这个程序比较特殊,此程序正好使用了键盘中断

正头疼中,好像程序无法装入中断向量表中,调试也没办法调试,看程序又没什么问题,汇编可真是麻烦啊!

人造人 发表于 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:                ;将原来 int 9 中断例程的指令的                        
                        pop ds:                        ;ip保存到ds:,cs保存到ds:单元中
                        push es:
                        pop ds:
                        
                        mov word ptr es:,offset int9
                        mov word ptr es:,cs      ;设置新的中断例程
                        
                        
                        mov ax,0b800h
                        mov es,ax
                        mov si,160*12+40*2
                        mov ah,'a'
                        
s:                        mov es:,ah
                        call delay      
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push ds:                        
                        pop es:
                        push ds:
                        pop es:

                        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:      ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:         ;属性增加1,改变颜色

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

end start

Cy86183570 发表于 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:                ;将原来 int 9 中断例程的指令的                       
                        pop es:
                        push es:                ;ip保存到0:200,cs保存到0:202
                        pop es:
                       
                        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:,204h                        ;设置新的中断例程
                        mov word ptr es:,0
                        sti                                ;恢复IF置1
                       
                        mov ax,0b800h
                        mov es,ax
                        mov ah,'a'
                       
s:                        mov es:,ah
                        call delay       
                        inc ah
                        cmp ah,'z'
                        jna s
                       
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push es:                       
                        pop es:
                        push es:
                        pop es:

                        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:        ;对int指令进行模拟,调用原来的int 9中断例程
                       
                        cmp al,1+80h
                        jne int9ret
                       
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:         ;属性增加1,改变颜色

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

end start

人造人 发表于 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:                ;将原来 int 9 中断例程的指令的                        
                        pop es:
                        push es:                ;ip保存到0:200,cs保存到0:202
                        pop es:
                        
                        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:,204h                        ;设置新的中断例程
                        mov word ptr es:,0
                        sti                              ;恢复IF置1
                        
                        mov ax,0b800h
                        mov es,ax
                        mov ah,'a'
                        
s:                        mov es:,ah
                        call delay      
                        inc ah
                        cmp ah,'z'
                        jna s
                        
                        mov ax,0                        ;中断例程的入口地址恢复为
                        mov es,ax                        ;原来的入口地址
                        push es:                        
                        pop es:
                        push es:
                        pop es:

                        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:      ;对int指令进行模拟,调用原来的int 9中断例程
                        
                        cmp al,1+80h
                        jne int9ret
                        
                        mov ax,0b800h
                        mov es,ax
                        inc byte ptr es:         ;属性增加1,改变颜色

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

end start

Cy86183570 发表于 2017-2-8 14:44:13

人造人 发表于 2017-2-8 14:25


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

人造人 发表于 2017-2-8 15:38:34

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

实模式?
下面gif如何解释

Cy86183570 发表于 2017-2-8 16:07:34

人造人 发表于 2017-2-8 15:38
实模式?
下面gif如何解释

不是啦,没改int 9程序的存储地址,我也能显示出来的

人造人 发表于 2017-2-8 17:15:40

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

不明白你在说什么,不过问题解决了进行
^_^
页: [1]
查看完整版本: int 9 中断例程