. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->外中断
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  13实验,潜在危险如何解决  [待解决] 回复[ 2次 ]   点击[ 239次 ]  
linguangliang
[帖 主]   [ 发表时间:2011-10-06 16:26 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-10-05 20:01
stack1        segment        stack
        dw        128        dup(?)
stack1        ends

data        segment
        dw        0,0
data        ends

assume cs:code,ss:stack1
code        segment
start:
        ;显示装入栈
        mov ax, stack1
        mov ss, ax
        mov sp, 128
        mov ax, data
        mov ds, ax
        ;保存原来9号中断向量并且装入新9号中断入口地址(即中断向量)
        xor ax, ax
        mov es, ax
        push es:[9*4]
        pop ds:[0]
        push es:[9*4+2]
        pop ds:[2]
        ;这样修改9号中断入口地址有潜在危险!,如果在执行mov word ptr es:[9*4], offset int9后刚好有键盘中断,那么由
        ;于此时ip被修改而cs未被修改,造成系统调用的int 9失败,这在debug下尤其如此,如果用t命令运行mov word         ;ptr es:[9*4], offset int9这一句时,系统会调用int 9,这样就出错了,当然在debug下我们可以用g命令直接把一下
        ;两句全部执行完这样不会有错误,但是没有根本解决错误,我们可以通过开关中断if来彻底解决次问题
        cli
        mov word ptr es:[9*4], offset int9
        mov es:[9*4+2], cs
        sti
        mov ax, 0b800h        ;得到显存内存地址
        mov es, ax
        mov al, 'a'
        ;在12行8列位置出依次显示出a-z
lop:        
        mov es:[160*12+40*2], al
        call delay                ;延时显示
        inc al
        cmp al, 'z'
        jna lop
        ;恢复9号中断的中断向量
        push ds:[0]
        pop es:[9*4]
        push ds:[2]
        pop es:[9*4+2]
        mov ah, 4ch
        int 21h
;delay函数,功能:延时,通过执行10000000h次空循环实现
delay:
        push dx
        push bx
        
        mov dx, 1000h
        mov bx, 0
s:        sub bx, 1
        sbb dx, 0
        cmp bx, 0
        jne s
        cmp dx, 0
        jne s
        pop bx
        pop dx
        ret
;自写新的int 9号中断,调用原int 9中断来忽略硬件细节,功能是检查输入是否为esc,若是,则改变字体颜色属性
int9:
        push ax
        push es
        
        pushf
        ;由于进入自写中断例程int9时,系统会自动设置tf=0,if=0,故可以省略下面程序
;        pushf
;        pop ax
;        and ah, 11111100b        ;tf,if标志位在第8,9位,tf=0,if=0
;        push ax
;        popf
        call dword ptr ds:[0]        ;调用原来int 9号中断忽略硬件细节
        
        in al, 60h        ;输入按键扫描码保存在60h端口中
        cmp al, 1        ;esc的扫描码为1
        jne int9ret
        mov ax, 0b800h
        mov es, ax
        inc byte ptr es:[160*12+40*2+1]        ;显存奇数列是保存其前面字符的颜色属性
int9ret:
        pop es
        pop ax
        iret 
code        ends
        end        start
//请详细看注释部分
chinatree
[第1楼]   [ 回复时间:2011-10-06 22:18 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
call dword ptr ds:[0]        ;调用原来int 9号中断忽略硬件细节
        in al, 60h        
这里和书上不一样,好像int 9需要一个参数由al传递吧,所以书上在调用前有句in al,60h
具体我也不太清楚。
zhujinwu
[第2楼]   [ 回复时间:2011-11-17 21:47 ]   [引用]   [回复]   [ top ] 
荣誉值:15
信誉值:0
注册日期:2011-11-03 09:29
这样改了之后也能运行。CPU在响应中断时:取得中断类型码;标志寄存器入栈;设置IF,TF为0;CS,IP入栈;(IP)=(9*4),(CS)=(9*4+2).其中并不需要额外的参数传递。“IN AL,60H”只是从60H端口取得所按键的字符码。
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved