zoukankan      html  css  js  c++  java
  • 汇编实验15:安装新的int 9中断例程

    汇编实验15:安装新的int 9中断例程

    任务

    安装一个新的int 9中断例程,功能:在DOS下,按下“A”键后,除非不在松开,一旦松开后,就显示满屏幕的“A”,其他键照常处理。

    预备知识概要

    这次实验其实不难,王爽的教材中已经给出了许多实例代码,依葫芦画瓢都能圆满完成任务。

    这次我们学习的是外中断,以外设的输入为例,CPU通过中断机制来处理外设的输入。

    外中断源分为两大类:

    • 可屏蔽中断
    • 不可屏蔽中断

    顾名思义,对于前者CPU可以选择不去响应中断,对于后者,CPU无论如何都要执行完当前指令后立即响应。

    不可屏蔽中断的中断过程很容易理解,在8086CPU中,它的中断类型码是固定的,就是2,接下来的过程和内中断一模一样。

    • 标志寄存器入栈,并设置IF=0,TF=0
    • 将CS,IP寄存器压栈
    • 使(IP) = (8) ,(CS) = (0AH)

    下面我们重点聊一聊可屏蔽中断

    IF标志位

    CPU通过IF标志为的状态来决定是否响应可屏蔽中断

    • 如果IF=1,CPU执行完当前指令后,响应中断,并引发中断过程
    • 如果IF=0,CPU不响应可屏蔽中断

    我们可以通过以下两条指令设置标志位IF

    • STI 设置标志位IF = 1
    • CLI 设置标志位IF = 0

    可屏蔽中断的中断过程

    可屏蔽中断的中断过程和内中断的过程几乎一模一样,只不过取得中断类型码的方式不同,可屏蔽中断的中断类型码是通过数据总线进入CPU的。
    为了表述完整,我还是总结一下这个中断过程(我怎么突然变勤快了吧,因为可以复制粘贴嘛!):

    • 获取中断类型码N(其实是为了获得中断例程的内存地址)
    • 标志寄存器入栈,并设置IF=0,TF=0
    • 将CS,IP寄存器压栈
    • 使(IP) = (4N) ,(CS) = (4N+2)

    键盘输入过程

    我们重点学习键盘输入的过程,总结起来就以下四步:

    • 键盘产生扫描码
    • 扫描码送入60h端口
    • 引发9号中断
    • CPU执行9号中断例程

    键盘的每一个键相当于一个开关,按下一个键,开关接通,键盘上的芯片产生一个扫描码(大小为一个字节),我们称它为“通码”,来说明按键的位置,然后送入主板上相关的接口芯片的寄存器中,就是60H端口。
    同样的,松开按键时,也会产生一个扫描码,然后被送入60H端口,这个扫描码被称为“断码”。

    同一个按键有两个扫描码,就是断码和通码,它们的区别就是最高位1和0的差别。
    可以总结为“断码 = 通码 + 80H”。

    最后说一下BIOS的键盘缓冲区,它能存储15个键盘输入。每个键盘输入占用两个字节大小的空间。高字节放扫描码,低字节放字符码(就是ASCII码)。

    代码实现

    虽然是自己编写int 9中断处理程序,但是我们没必要完整的处理一个键盘的输入,中间涉及一些硬件细节,会偏离内容主线(总之就是现在的你太菜了,怕你伤自尊,就不告诉你了)。没关系,对于硬件细节的处理,交给BIOS的int 9的中断例程就好了嘛!

    为此,王爽的书里就讲了一些技巧,比如怎么用汇编指令模拟int中断过程,怎么在已经修改了中断向量表的情况下,调用原始的BIOS的int 9中断例程。详细内容请见王爽的《汇编语言(第三版)》(我真的不想在打字了)

    下面贴出我的代码:

    assume      cs:code,ss:stack
    
    stack       segment
        db 256 dup(0)
    stack       ends
    
    code        segment
    
    main:       mov     ax,stack
                mov     ss,ax
                mov     sp,256
    
                call    install
        s:      jmp     s
    
                mov     ax,4c00h
                int     21h
    ;********************************************************
    install:    ;寄存器保护
                push    ax
                push    cx
                push    si
                push    di
                push    ds
                push    es
                ;将中断处理程序do9安装到内存单元0:204h中
                push    cs
                pop     ds
                mov     si,offset do9
    
                mov     ax,0
                mov     es,ax
                mov     di,204h
                mov     cx,offset do9end - offset do9
                cld
                rep     movsb
                ;保存BIOS的9号中断例程地址
                push    es:[9*4]
                pop     es:[200h]          ;偏移地址存放到内存单元0:200h中
                push    es:[9*4+2]
                pop     es:[202h]          ;段地址存放到内存单元0:202h中
    
                ;修改原来的中断向量表,此过程中不响应可屏蔽中断
                cli
                mov     word ptr es:[9*4],204h
                mov     word ptr es:[9*4+2],0
                sti
                ;恢复寄存器
                pop     es
                pop     ds
                pop     di
                pop     si
                pop     cx
                pop     ax
                ret
    ;----------------------------------------------------
    do9:        push    ax
                push    bx
                push    cx
                push    es
    
                in      al,60h
    
                pushf
                call    dword ptr cs:[200h]
    
                cmp     al,9eh      ;A键的断码为9eh
                jne     do9ret
    
                ;显示满屏幕的字符A
                mov     ax,0b800h
                mov     es,ax
                mov     bx,0
                mov     cx,2000
        do9_s:  mov     byte ptr es:[bx],'A'
                add     bx,2
                loop    do9_s
    
    do9ret:     pop     es
                pop     cx
                pop     bx
                pop     ax
                ret
    ;----------------------------------------------------
    do9end:     nop
    code        ends
    
    end     main

    对,你没看错,这回的代码是有注释的!(我其实还是挺勤快的)。下面是执行的结果:

    按下A键不松手

    按下A键松手后

    总结

    这几次的实验其实都没有什么挑战性,都是依葫芦画瓢,只要熟悉教材前面的示范代码,都可以轻松的完成实验。关键就是对CPU中断机制和中断过程的理解。毕竟,在以后的学习中,我们不可能真的要自己用16位的汇编语言自己写一个中断处理程序(不然我选择狗带)。关键是对加深对计算机的理解,对汇编语言有个初步的认识与体验,为今后的学习作一定的铺垫(我其实挺想知道高级语言怎么编译成相应的机器指令的,可惜由于专业原因,这辈子都学不到了……可以自学……如果我不是个懒人的话……)。

  • 相关阅读:
    try catch finally
    类的小练习
    易混淆概念总结
    C#中struct和class的区别详解
    Doing Homework again
    悼念512汶川大地震遇难同胞——老人是真饿了
    Repair the Wall
    Saving HDU
    JAVA-JSP隐式对象
    JAVA-JSP动作
  • 原文地址:https://www.cnblogs.com/wyf12138/p/6581524.html
Copyright © 2011-2022 走看看