![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-04 04:59 |
共 48,038 主题排行 / 350,123 发帖 / 今日 0 篇 / 48,251 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 关于汇编改写中断入口地址 的问题。 |
| 可打印版本 3,448 / 15 |
| 第1楼 zhushouqqq | 发表于 2008-12-03 18:26 |
| 初级用户 发帖 13 积分 32 | |
|
关于汇编改写中断入口地址 的问题。 在程序运行期间 修改了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 继续研究。。。 |
|
| 第2楼 本是 | 发表于 2008-12-03 21:16 |
| 银牌会员 发帖 790 积分 2,227 | |
|
你的问题出在这段程序上,你的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 ;循环显示 |
|
| 第3楼 zhushouqqq | 发表于 2008-12-04 09:58 |
| 初级用户 发帖 13 积分 32 | |
|
恩 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 恢复。 |
|
| 第4楼 本是 | 发表于 2008-12-04 11:28 |
| 银牌会员 发帖 790 积分 2,227 | |
|
DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。
另外,你的新例程中,DI值来自何处?而且也没有处理键盘输入的程序行,应该是程序不完整吧!因为贴出来的程序段根本不需要挂在int9上。 [ Last edited by 本是 on 2008-12-4 at 11:43 ] |
|
| 第5楼 zhushouqqq | 发表于 2008-12-04 12:11 |
| 初级用户 发帖 13 积分 32 | |
|
mov di,160*12+2*40 ;第13行中间开始
因为这个中断例程只是这个程序用 程序执行玩后 就要恢复的 所以这个DI 在在例程中没有重新赋值。 “DOS中断最要注意重入问题,要调用原中断例程,要在int99(新中断例程)中加入pushf和call dword ptr ds:int9ip链接原中断,才能继续键盘操作。” 对这句话不是很理解。 中断产生,也就是我按下键盘 产生的int 9中断。 硬件完成了Cs IP 标志寄存器的入栈, 然后就是调用我的int99 我只要在中断历程中iret一下就可以了。 鄙人不才,还望进一步指点。 |
|
| 第6楼 zhushouqqq | 发表于 2008-12-04 12:44 |
| 初级用户 发帖 13 积分 32 | |
|
是不是这样,
我在程序中只是执行了 我定义的int 9中断 但是还要必须执行一次系统原来的int 9中断。 |
|
| 第7楼 zhushouqqq | 发表于 2008-12-04 12:59 |
| 初级用户 发帖 13 积分 32 | |
|
中断例程修改如下:
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中断 做了些什么。 |
|
| 第8楼 zhushouqqq | 发表于 2008-12-04 13:00 |
| 初级用户 发帖 13 积分 32 | |
|
谢谢 本是
这个问题困扰了我三天。 |
|
| 第9楼 本是 | 发表于 2008-12-04 13:45 |
| 银牌会员 发帖 790 积分 2,227 | |
|
不用谢!不过,我觉得你需要系统地学习一些系统知识,如《MS-DOS高级开发指南——编程人员必备的高级技术参考书》(希望电脑公司),里面对中断编程讲得很细,当然网上也应该有资料的。
|
|
| 第10楼 netwinxp | 发表于 2008-12-05 11:15 |
| 高级用户 发帖 366 积分 741 | |
|
硬件中断服务程序要注意与硬件的“沟通”,你的INT 9既没有对产生INT 9的原因进行“处理”,也没有回调老的中断服务程序进行默认的“处理”,于是,按一下键,就会一直在产生INT 9。
|
|
| 第11楼 本是 | 发表于 2008-12-05 11:22 |
| 银牌会员 发帖 790 积分 2,227 | |
Originally posted by netwinxp at 2008-12-5 11:15: 真正的硬件高手!一直喜欢看高手回的贴子。 |
|
| 第12楼 zhushouqqq | 发表于 2008-12-12 09:15 |
| 初级用户 发帖 13 积分 32 | |
Originally posted by netwinxp at 2008-12-5 11:15: 不是一直产生int 9 而是8259A不让通过 因为在接受一个中断后 8259A的EOI位一直为0,不在接受同级或以下级别的中断(被屏蔽了)。 直到EOI标志位为1。 我想,要在进行一次默认的“处理”,其目的是让EOI置1.代码修改后 测试通过 int9: mov ah,0fch mov byte ptr es:,ah ;恢复向量表 mov al,20h out 20h,al ;置EOI 为1 iret |
|
| 第13楼 netwinxp | 发表于 2008-12-12 09:25 |
| 高级用户 发帖 366 积分 741 | |
|
其实你的程序根本没必要使用INT 9,除非迫不得已,否则不推荐任意修改硬件中断服务程序。
... RE: ... ;寄存器入栈 ;清理标志寄存器 mov ax,1100H int 16H jnz EXIT ;寄存器出栈 ;用于显示的语句 ... jmp RE EXIT:;退出处理 ... [ Last edited by netwinxp on 2008-12-12 at 09:31 ] |
|
| 第14楼 zhushouqqq | 发表于 2008-12-12 09:46 |
| 初级用户 发帖 13 积分 32 | |
|
这个只是书上一个运行不起来的代码。只是为了自己理解。
|
|
| 第15楼 sanchuan | 发表于 2008-12-30 17:10 |
| 初级用户 发帖 51 积分 113 来自 武汉 | |
|
能够引起探讨的好贴,顶
|
|
| 1 2 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |