|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『楼 主』:
关于汇编改写中断入口地址 的问题。
在程序运行期间 修改了int9的入口地址 程序结束 恢复int9的入口地址
程序的执行从结果上看是正常的 结束后,键盘就锁住了。
以下是代码。
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0
int9cs dw 0
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,0
mov es,ax
mov si,0
mov dx,es:[9*4]
mov word ptr int9ip,dx
mov dx,es:[9*4+2]
mov word ptr int9cs,dx ;保存当前的int 9的中断向量
;
mov word ptr es:[9*4],offset int99
mov word ptr es:[9*4+2],cs ;设置int 9中断向量
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
mov dx,int9ip
mov word ptr es:[9*4],dx
mov dx,int9cs
mov word ptr es:[9*4+2],dx ;恢复int 9中断向量
mov ax,4c00h
int 21h
;----------------------------------
int99: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
iret
;----------------------------------
;用于延时
time proc
push ax
push bx
mov bx,1000h
mov ax,0
s1:
sub ax,1
sbb bx,0
cmp ax,0
jne s1
cmp bx,0
jne s1
pop bx
pop ax
ret
time endp
codesg ends
end start
继续研究。。。
|
|
2008-12-3 18:26 |
|
|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『第
2 楼』:
你的问题出在这段程序上,你的ES被替换后未做现场保护,只要在前面加PUSH ES,在后面加POP ES就可以了。我在编VtMagiC.com时也有过如此疏漏导致的调试多次失败。汇编就是这样的!所以人家要用VB、VC啦!
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-3 21:16 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
3 楼』:
恩 ES确实没有保护好
以下是改后的代码 我全贴出来吧, 复制过去,编译下就能运行
我想实现的功能是这样的, 在逐个显示字符期间, 如果有键盘按键。就改变原来的字符颜色。 并用改写int 9 中断的方式去实现。
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
db 128 dup(0)
stacksg ends
datasg segment
int9ip dw 0
int9cs dw 0
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,0
mov es,ax
mov si,0
mov dx,es:[9*4]
mov word ptr int9ip,dx
mov dx,es:[9*4+2]
mov word ptr int9cs,dx ;保存当前的int 9的中断向量
;
mov word ptr es:[9*4],offset int9
mov word ptr es:[9*4+2],cs ;设置int 9中断向量
push es
mov ax,0b800h
mov es,ax
mov di,160*12+2*40 ;第13行中间开始
mov cx,10
;
mov al,'a'
mov ah,7ch ;颜色
mov es:[di+1],ah
;
s:
mov es:[di],al
call time
inc al
loop s ;循环显示
pop es
mov dx,int9ip
mov word ptr es:[9*4],dx
mov dx,int9cs
mov word ptr es:[9*4+2],dx ;恢复int 9中断向量
mov ax,4c00h
int 21h
;----------------------------------
int9: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
iret
;----------------------------------
;用于延时
time proc
push ax
push bx
mov bx,1000h
mov ax,0
s1:
sub ax,1
sbb bx,0
cmp ax,0
jne s1
cmp bx,0
jne s1
pop bx
pop ax
ret
time endp
codesg ends
end start
程序运行 和第一次的结果一样, 在显示字符期间按键盘,字符颜色就改变。 但是,程序运行结束 键盘就不能用了,输入不了字符了。
另外,我在time子程序里 S标号的上一句加了 int 9让程序自身产生中断。 运行结果是,字符的颜色改变,键盘能用。 这就奇怪了直接在程序里写int 9和按键触发的int 9应该一样呀 都是是cs ip 寄存器 入栈。iret 恢复。
|
|
2008-12-4 09:58 |
|
|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『第
4 楼』:
DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。
另外,你的新例程中,DI值来自何处?而且也没有处理键盘输入的程序行,应该是程序不完整吧!因为贴出来的程序段根本不需要挂在int9上。
[ Last edited by 本是 on 2008-12-4 at 11:43 ]
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-4 11:28 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
5 楼』:
mov di,160*12+2*40 ;第13行中间开始
因为这个中断例程只是这个程序用 程序执行玩后 就要恢复的 所以这个DI 在在例程中没有重新赋值。
“DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。”
对这句话不是很理解。
中断产生,也就是我按下键盘 产生的int 9中断。 硬件完成了Cs IP 标志寄存器的入栈, 然后就是调用我的int99 我只要在中断历程中iret一下就可以了。
鄙人不才,还望进一步指点。
|
|
2008-12-4 12:11 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
6 楼』:
是不是这样,
我在程序中只是执行了 我定义的int 9中断 但是还要必须执行一次系统原来的int 9中断。
|
|
2008-12-4 12:44 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
7 楼』:
中断例程修改如下:
int9: ;到这里 CS IP 标志寄存器 已经由硬件完成入栈
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
pushf push ax
and ah,11111100b
pop ax
;push int9cs
;push int9ip
;jmp dword ptr int9ip ;高地址是cs 低地址是IP
call dword ptr ds:int9ip ;模仿 调用系统的int 9
iret
运行正常 看来还要好好的深入研究中断
系统的int 9中断 做了些什么。
|
|
2008-12-4 12:59 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
8 楼』:
谢谢 本是
这个问题困扰了我三天。
|
|
2008-12-4 13:00 |
|
|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『第
9 楼』:
不用谢!不过,我觉得你需要系统地学习一些系统知识,如《MS-DOS高级开发指南——编程人员必备的高级技术参考书》(希望电脑公司),里面对中断编程讲得很细,当然网上也应该有资料的。
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-4 13:45 |
|
|
netwinxp
高级用户
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第
10 楼』:
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。
|
|
2008-12-5 11:15 |
|
|
本是
银牌会员
积分 2201
发帖 789
注册 2005-1-27
状态 离线
|
『第
11 楼』:
Quote: | Originally posted by netwinxp at 2008-12-5 11:15:
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。 |
|
真正的硬件高手!一直喜欢看高手回的贴子。
|
my major is english----my love is dos----my teacher is the buddha----my friends--how about U |
|
2008-12-5 11:22 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
12 楼』:
Quote: | Originally posted by netwinxp at 2008-12-5 11:15:
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。 |
|
不是一直产生int 9 而是8259A不让通过 因为在接受一个中断后 8259A的EOI位一直为0,不在接受同级或以下级别的中断(被屏蔽了)。 直到EOI标志位为1。 我想,要在进行一次默认的“处理”,其目的是让EOI置1.代码修改后 测试通过
int9:
mov ah,0fch
mov byte ptr es:[di+1],ah ;恢复向量表
mov al,20h
out 20h,al ;置EOI 为1
iret
|
|
2008-12-12 09:15 |
|
|
netwinxp
高级用户
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第
13 楼』:
其实你的程序根本没必要使用INT 9,除非迫不得已,否则不推荐任意修改硬件中断服务程序。
...
RE:
...
;寄存器入栈
;清理标志寄存器
mov ax,1100H
int 16H
jnz EXIT
;寄存器出栈
;用于显示的语句
...
jmp RE
EXIT:;退出处理
...
[ Last edited by netwinxp on 2008-12-12 at 09:31 ]
|
|
2008-12-12 09:25 |
|
|
zhushouqqq
初级用户
积分 32
发帖 13
注册 2008-12-2
状态 离线
|
『第
14 楼』:
这个只是书上一个运行不起来的代码。只是为了自己理解。
|
|
2008-12-12 09:46 |
|
|
sanchuan
初级用户
积分 113
发帖 51
注册 2008-11-16 来自 武汉
状态 离线
|
『第
15 楼』:
能够引起探讨的好贴,顶
|
三川一笑 |
|
2008-12-30 17:10 |
|