|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
子程序功能: 在屏幕中间依次显示'a'~'z', 一个字母要在屏幕中间停留一段时间。在显示过程中, 按下'Esc'键后, 改变显示的颜色
问题: 每次调试到mov es:[4 * 9 + 2], cs(第27行), 就会出现一个ü然后什么都没法输入
- assume cs: code, ss: stack, ds: data
- stack segment
- db 128 dup(0)
- stack ends
- data segment
- dw 0, 0
- data ends
- code segment
- start:
- mov ax, stack
- mov ss, ax
- mov sp, 128
- mov ax, data
- mov ds, ax
- mov ax, 0
- mov es, ax
- push es:[9 * 4]
- pop ds:[0]
- push es:[9 * 4 + 2]
- pop ds:[2] ; 将9号例程的入口地址保存起来
- mov word ptr es:[4 * 9], offset int9
- mov es:[4 * 9 + 2], cs ; 设置新的9号例程的入口地址
- mov ax, 0b800h
- mov es, ax
- mov ah, 'a'
- s:
- mov es:[160 * 12 + 40], ah
- call delay
- inc ah
- cmp ah, 'z'
- jna s
- mov ax, 0
- mov es, ax
- push ds:[0]
- pop es:[4 * 9]
- push ds:[2]
- pop es:[4 * 9 + 2] ; 恢复int9中断例程的地址
- mov ax, 4c00h
- int 21h
- delay:
- push ax
- push dx
- mov dx, 06h
- mov ax, 0 ; 延迟每个字母的显示时间
- s_:
- sub ax, 1
- sbb dx, 0
- cmp ax, 0
- jne s_
- cmp dx, 0
- jne s_
- pop dx
- pop ax
- ret
- ; -----------以下为新的int9中断例程----------
- int9:
- push ax
- push bx
- push es
- in al, 60h ; 读取60h端口数据, 获取键盘扫描码, 60h端口默认与键盘输入挂钩
- pushf ; 保留原本的标志寄存器的值
- pushf
- pop bx
- and bx, 11111100b
- push bx
- popf ; 把IF和TF置零
- call dword ptr ds:[0] ; 模拟int指令, 调用原来的int9中断例程
- cmp al, 1 ; 1是ESC键的键盘扫描码
- jne int9ret
- mov ax, 0b800h
- mov es,ax
- inc byte ptr es:[160 * 12 + 40 + 1] ;属性增加1,改变颜色
- int9ret:
- pop es
- pop bx
- pop ax
- iret
- code ends
- end start
复制代码
可以看到用g命令连续执行这两条指令,一切正常
int9入口地址成功的从 0x04b3:0x1923 修改成了 0x11b3:0x007f
注意看图,最后显示出的寄存器中,cs寄存器的值是 0x11b3
如果是用t命令分开执行这两条指令,就出问题了
我是先输入字符 t,然后下的内存读断点和写断点
然后按下回车键,然后触发了内存断点
如果在输入字符 t 之前就下断点,那在输入字符 t 的时候也会触发内存断点
这样会输出更多的数据,会影响对输出的这些数据的分析,这样不好,所以我先输入字符 t,然后下的内存读断点和写断点
从图中可以看到,按下回车键后,int9入口从 0x04b3:0x1923 修改成了 0x04b3:0x007f
你没有看错,的确是修改成了 0x04b3:0x007f
因为你只改了偏移地址,改段地址的指令还没有执行,所以段地址还保持之前的值
接下来又触发了一次中断,执行了 0x04b3:0x007f 位置的指令,这里无法理解?
这里我解释一下
你按下键盘上的某一个键,然后松开,这会发生两次键盘中断
一次是按键按下的中断,另一次是按键弹起的中断
所以,在按键按下的中断中把int9入口改成 0x04b3:0x007f
在弹起的这一次中断就执行 0x04b3:0x007f
0x04b3:0x007f 这里是什么?
看反汇编的结果,这里不像是指令,你硬是把数据作为指令来执行,然后就出问题了
如果你足够细心,你会发现中断向量表中的地址是 0x04b3:0x007f,捕获到内存断点停下来显示出的地址是 0x04b3:0x0081
这是因为在捕获到这个内存读写信号的时候,读写内存的那条指令已经执行了,调试器选择显示cs:ip的位置
要显示修改内存的那条指令我不知道能不能做到,就算能,也真的很麻烦(我感觉是这样),而显示cs:ip的位置会很简单
|
评分
-
查看全部评分
|