189 8069 5689

汇编语言第十五章外中断小白笔记-创新互联

15.1 接口芯片和端口

pc 系统的接口卡和主板上,装有各种接口芯片。这些外设接口芯片内部有若干寄存器,cpu将这些寄存器当作端口来访问。

我们提供的服务有:成都网站设计、网站制作、外贸营销网站建设、微信公众号开发、网站优化、网站认证、呼图壁ssl等。为1000+企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的呼图壁网站制作公司

cpu通过端口和外部设备进行联系。

15.2 外中断信息

来自外部的中断信息

外部中断原有两类:

第一类:可屏蔽中断源

cpu是否响应中断要看标志寄存器。if=1的话,执行完当前指令后去响应中断。if=0的话,不响应中断。

内中断的过程:

(1)取中断类型码n

(2)标志寄存器入栈,if=0,tf=0

(3)cs、ip入栈

(4)(ip)=(n*4),(cs)=(n*4+2)

if=0就是为了屏蔽其他的可屏蔽中断

指令:

sti   ;if=1
cli   ;if=0
第二类:不可屏蔽中断

cpu必须响应。

8086cpu不可屏蔽终端类型码固定为2,所以屏蔽过程中不需要取中断类型码。

过程:

(1)标志寄存器入栈,if=0,tf=0

(2)cs ip入栈

(3)(ip)=(8),(cs)=(0ah)

15.3pc键盘的处理过程

    • 键盘输入

键盘中每个按键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。

按下一个键时,开关接通,芯片会产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60h

松开按下的键时,也会产生一个扫描码,扫描码说明了松开的键在键盘上的位置,松开按键时产生的扫描码也会被送入60h端口中。

一般按下键盘时的扫描码被叫做通码,松开时的扫描码叫做断码。扫描码长度为一个字节,通码第7位为0,断码第七位为1

就是:

断码=通码+80h
    • 引发9号中断

键盘的输入到达60h端口时,相关的芯片就会向cpu发出中断类型码为9的可屏蔽中断信息。

cpu检测到该中断信息后,如果if=1,则响应中断,引发中断过程,转去执行int9中断例程

    • 执行int9中断例程

(BIOS)系统板的ROM(只读内存)中放有一套程序,称为BIOS(基本输出输入系统)

BIOS提供了int9 的中断例程,用来进行键盘的读取和输出。

:(1)读出60h端口中的扫描码

(2)如果是字符键的扫描码,将该扫描码和它所对应的字符码(ascll)送入内存(一个字节加一个字节=一个字),=中的BIOS键盘缓冲区,如果是控制键的扫描码,则将其转化成状态字节(用二进制记录控制键和切换键状态字节)写入内存中储存状态字节的单元(内存单元)。

(3)对键盘系统进行相关的控制,比如像向芯片发出应答信息

BIOS键盘换缓冲区是系统启动后,BIOS用于存放int9 中断例程所接受的键盘输入的内存区。该内存区可以存储15个键盘输入(15个字型数据),因为int9 中断例程除了接收扫描码外还要产生扫描码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位存放扫描码,低位存放字符码(ascll)。

assume cs:code,ds:data,ss:stack
data segment
         db 128 dup(0)
data ends

stack segment stack
          db 128 dup(0)
stack ends




code segment

    start:             mov  ax,stack
                       mov  ss,ax
                       mov  sp,128
                        call init_reg
                       call show_keywordstatus



                       mov  ax,4C00h
                       int  21h

    ;===============================
    init_reg:          mov  bx,0B800h

                       mov  es,bx
                       mov  bx,40h
                       mov  ds,bx

                       ret
    ;====================================
    show_status:       push cx
                       push dx
                       push ds
                       push es
                       push si
                       push di

    
    
                       mov  cx,8
     
    showstatus:        mov  dx,0


                       shl  al,1
                       adc  dx,30h
                       mov  es:[di],dl
                       add  di,2
                       loop showstatus
                        

                       pop  di
                       pop  si
                       pop  es
                       pop  ds
                       pop  dx
                       pop  cx

                       ret

    ;===========================
    show_keywordstatus:

                       mov  si,17h
    testA:             
                       mov  di,160*10+40*2
                       mov  al,ds:[si]
                      
                       call show_status

                       jmp  testA
                       ret


code ends

end start
15.4 编写int9中断例程

键盘的输入处理过程:

  1. 键盘产生扫描码

  1. 扫描码送入60h端口

  1. 引发9号中断

  1. cpu执行int9中断例程处理键盘输入

编程:在屏幕中依次显示'a'~'z' esc后改变颜色。

由于cpu执行速度太快,所以要在每一次输入后都进行好多次循环来延迟时间。

assume cs:code
stack segment
          db 128 dup (0)
stack ends



code segment
    start:mov  ax,stack
          mov  ss,ax
          mov  sp,128
    
          mov  ax,0b800h
          mov  es,ax
          mov  ah,'a'
    s:    mov  es:[160*12+40*2],ah


          call delay

          inc  ah
          cmp  ah,'z'
          jna  s
          mov  ax,4c00h
          int  21h



    delay:push ax
          push dx
          mov  dx,10h
          mov  ax,0

    s1:   sub  ax,1
          sbb  dx,0
          cmp  ax,0
          jne  s1
          cmp  dx,0
          jne  s1
          pop  dx
          pop  ax
          
          
          ret





code ends

    end start

改变颜色

那个咱就是说代码一定不要放到vscode的安装目录中

assume cs:code
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]                               ;将原来的int9中断例程,的入口保存在ds:0、ds:2中
                cli
                mov   word ptr es:[9*4],offset int9
                mov   es:[9*4+2],cs                        ;在中断向量表中设置新的int9 中断例程的入口地址
                sti





                mov   ax,0b800h
                mov   es,ax
                mov   ah,'a'
        s:      mov   es:[160*12+40*2],ah


                call  delay

                inc   ah
                cmp   ah,'z'
                jna   s

                mov   ax,0
                mov   es,ax

                push  ds:[0]
                pop   es:[9*4]
                push  ds:[2]
                pop   es:[9*4+2]                           ;将中断向量表中int9中断例程的入口恢复为原来的地址





                mov   ax,4c00h
                int   21h



        delay:  push  ax
                push  dx
                mov   dx,10h
                mov   ax,0

        s1:     sub   ax,1
                sbb   dx,0
                cmp   ax,0
                jne   s1
                cmp   dx,0
                jne   s1
                pop   dx
                pop   ax
          
          
                ret


        ;======================================
        int9:   push  ax
                push  bx

                push  es

                in    al,60h                               ;从端口60h读取键盘的输入数据

        ;原来的int调用是(取中断码类型)->(标志寄存器入栈)->(if=0,tf=0)->(cs、ip入栈)->(ip=n*4,cs=n*4+2)
        ;我们将地址放到ds中,所以第一步可省,那么就剩(标志寄存器入栈)->(if=0,tf=0)->(cs、ip入栈)->(ip=n*4,cs=n*4+2)
        ;(cs、ip入栈)->(ip=n*4,cs=n*4+2)==call dword ptr ds:[0]
        ;那么就剩(标志寄存器入栈)->(if=0,tf=0)->call dword ptr ds:[0]三步
        ;
        ;






                pushf                                      ;标志寄存器入栈
        ;   pushf
        ;   pop   bx
        ;   and   bh,11111100b    ;标志寄存器if=tf=0
        ;   push  bx
        ;   popf
                call  dword ptr ds:[0]                     ;模拟int指令,调用原来的int9中断例程

                cmp   al,1
                jne   int9ret

                mov   ax,0b800h
                mov   es,ax
                inc   byte ptr es:[160*12+40*2+1]          ;属性值加1改变颜色


        int9ret:pop   es
                pop   bx
                pop   ax
                iret


code ends

    end start
15.5安装新的int9中断例程序

按下F1后屏幕颜色改变

大概思路就是先将自己写好的int9机器码复制粘贴到0:204

需要先将老int9的csip存到0:200

然后改变中断信息表int9为新的int9的csip

新的int9中会使用call调用老的int9

然后进行判断如果是某个键就进行啥啥

其实就是在原来的int9前边加了一点东西

assume cs:code

stack segment stack
          db 128 dup(0)
stack ends




code segment

    start:  mov   ax,stack
            mov   ss,ax
            mov   sp,128


            push  cs
            pop   ds

            mov   ax,0
            mov   es,ax


            mov   si,offset int9
            mov   di,204h
            mov   cx,offset int9end-offset int9
            cld

            rep   movsb

            push  es:[9*4]
            pop   es:[200h]
            push  es:[9*4+2]
            pop   es:[202h]

            cli
            mov   word ptr es:[9*4],204h
            mov   word ptr es:[9*4+2],0
            sti
          



            mov   ax,4C00h
            int   21h

    int9:   push  ax
            push  bx
            push  cx

            push  es
            in    al,60h

            pushf
            call  dword ptr cs:[200h]

            cmp   al,3bh
            jne   int9ret

            mov   ax,0b800h
            mov   es,ax
            mov   bx,1
            mov   cx,2000
    s:      inc   byte ptr es:[bx]

            add   bx,2
            loop  s


    int9ret:pop   es
            pop   cx
            pop   bx
            pop   ax
            iret
    int9end:nop



code ends

end start

实验15 安装新的int9中断例程

按下“A”后除非不松开,只要松开就出现满屏的"A"

直接根据前边那个改的

先将老int9挪到一边,在新得int9中用call调用老int9

新的int9可以在调用之后加一些功能

assume cs:code

stack segment stack
          db 128 dup(0)
stack ends

code segment

    start:  mov   ax,stack
            mov   ss,ax
            mov   sp,128


            push  cs
            pop   ds

            mov   ax,0
            mov   es,ax


            mov   si,offset int9
            mov   di,204h
            mov   cx,offset int9end-offset int9
            cld

            rep   movsb

            push  es:[9*4]
            pop   es:[200h]
            push  es:[9*4+2]
            pop   es:[202h]

            cli
            mov   word ptr es:[9*4],204h
            mov   word ptr es:[9*4+2],0
            sti
          



            mov   ax,4C00h
            int   21h

    int9:   push  ax
            push  bx
            push  cx

            push  es
            in    al,60h

            pushf
            call  dword ptr cs:[200h]

            cmp   al,1eh+80h
            jne   int9ret

            mov   ax,0b800h
            mov   es,ax
            mov   bx,0
            mov   cx,2000
    s:      mov  byte ptr es:[bx],'A'

            add   bx,2
            loop  s


    int9ret:pop   es
            pop   cx
            pop   bx
            pop   ax
            iret
    int9end:nop



code ends

end start

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享标题:汇编语言第十五章外中断小白笔记-创新互联
网页网址:http://jkwzsj.com/article/didspo.html

其他资讯