zoukankan      html  css  js  c++  java
  • 终于把int 8h调通了

    摘要:
    ---------------------------------------------------------------------------------------
     

    最近一直在折腾int8h,明明已经把中断处理程序的入口地址注册到0000:0020处,显式调用int8h可以正常转移到中断处理程序,但就是不可以自动中断。
     后来还是在于渊前辈的书里找到答案,“说起EOI,如果你有过在实模式下的编程经验,那么对它因该不会陌生。当每一次中断处理结束,需要发送一个EOI给8259A,以便继续接受中断”。
      于是我在程序中加了两行代码:
      mov al,20h
      out 20h,al
      编译测试,果然每秒18.2次的中断跑起来了。
     ---------------------------------------------------------------------------------------

    讲讲经过
    下面是那段存在错误的代码:
    -------------------------------------------------
    %include "echoinit.mac"
    %include "./echon.mac";这两个头文件是我自己写的多行宏,用来实现类似c语言printf的功能,已专门测试过,没有问题
    org 0x7c00
    enter:jmp start
    handler:echon 'hello oranges world'
    iret ;handler标签处是int 8h的中断处理程序,预期的效果是屏幕从上向下重复打印出'hello orangesworld'
         ;但实际运行起来什么现象也没有
    start:echoinit ;这个宏是echon宏的初始化,都是我自己定义的,不用管它
    setup:
    mov ax,0 ;在8*4内存地址处注册中断处理程序的入口地址
    mov ds,ax
    mov bx,32
    mov word [bx],handler-$$
    mov word [bx+2],07c0h
    ;int 8h ;这一行不注释的话,会出现附图1效果--->这说明8h中断的处理程序安装成功
    jmp $
    times 510-($-enter) db 0
    dw 0aa55h
    -------------------------------------------------
    终于把int <wbr>8h调通了
    附图1(上图)

      我预期的效果是屏幕从上向下重复打印出'hello orangesworld‘,现在什么现象都没有。显然是cpu并没有响应8253A的0通道所不断发出的8号中断。
     最先想到的(确切说是从网上查到的)是忘了加sti,导致全局中断屏蔽,于是我加上一句sti打开中断,编译测试,出现下图画面:

    终于把int <wbr>8h调通了
    附图2(上图)
      跟附图1一模一样是不是?但别忘了:图1是手动调用int8h得到的结果,图2对应的代码已经将int 8h注释掉了,并且加了一句sti。这说明sti产生了效果,它的确使cpu响应了int8h中断!但效果不佳:cpu只响应了1次就熄火儿了。
     我琢磨了一下:大概是bochs虚拟机的问题,它为了实现单步调试,可能不断的用cli指令屏蔽中断。于是我就用不带调试功能的bochs测试了一下,依然是同样画面。
     我不死心,心想可能不带调试功能的bochs也有问题,于是在bochs上装了freedos,另外写了一段程序(因为我那个echon宏在com文件里不能用),编译成boot.com文件来做测试。下面是那段代码:
    ---------------------------------------------------------------------------------------
    entrance:jmp setup
    handler: 
        movax,0xb800
        moves,ax
        mov byte[es:di],dl
        adddi,2                       ;es:di指向屏幕下一个字符对应的内存地址
        inc dl                      ;dl自增1,即产生a,b,c,d,e...的效果 
        iret
    setup:  mov dl,'b'
        movdi,0                      ;初始化es:di指向屏幕第一个字符对应的内存地址
        movbx,32                   ;8h中断的中断表项在0000h:0020h处
        movax,0
        movds,ax
       mov  word [ds:bx],handler-entrance+100h;将中断处理程序的入口地址登记到中断向量表
        movax,cs
        movword  [ds:bx+2],ax
        sti
    jmp $
    ---------------------------------------------------------------------------------------
      代码想实现的效果是:从屏幕左上角,从左到右一次显示a,b,c,d,e.....
      编译nasm -o boot.com boot.asm
      dos下测试,画面如下:
    终于把int <wbr>8h调通了
    很悲据吧!只有第一个字母变成了b,然后画面就一动不动了!显然cpu又是只相应了一次8h中断就哑火了。

     这一连串的失败让我重新怀疑问题出现在自己的代码上,于是我就大致看了看8259A中断控制器的原理:IR0接8253A的0通道的时钟中断,优先级最高,bios开机即将IR0的中断码设为8H....IMR的8个位分别对应IR0~IR7的开关...
      难道是IMR的对应位将int 8h屏蔽掉了,因为IMR的端口是21h,我在代码中加了一条inal,21h,编译之后bochs调试,这条指令执行之后,info cpu显示:al=b8即IMR的值是10111000  IR0对应的0,说明int8h中断未被屏蔽!哎,当时真是很绝望,我可不想再把微机原理8259A彻头彻尾学一遍!
      这时翻了翻于渊前辈的书,竟然得知世界上还有EOI这个东西...
      算是比较幸运吧...
      程序正常跑起来之后是这样:
      终于把int <wbr>8h调通了

    上图是dos下那个程序,开头正是我想要的b,c,d,e....后面的乱码是可以理解的:al超过256后,就不再是ascii有效值了(其实是个动态的逐渐打印的过程,可惜做成gif文件太麻烦)
    终于把int <wbr>8h调通了

    上图是bochs下那个程序,前面写掉了个h,但哪里在乎这!等了这么长时间的画面一下子跳到眼前,赶忙抓下来了。
     现在回想一下之前的怪异现象:cpu响应一次8h中断就熄火儿。原因无非是中断处理程序结束的时候,并没有发送一个EOI到8259A,于是它便无法继续接受中断...于是哑火儿了。嘀咕一句,这个EOI不知道跟cpu的INTA信号有关系没(我现在是懒得学更多了,弄不懂先放着,原先只是想在另一个程序里用一下int8h,结果费了这么大周折)
    遇到的一个介绍8259A的视频,是吉大的微机原理,讲的还可以:http://www.xuexun.com/C_23660.shtml
  • 相关阅读:
    elementui 修改合计行样式
    C# 导出Excel NPOI 修改指定单元格的样式 或者行样式
    向基于语义模型的操作集成的演变
    在制造业的工业2.0中应用MOM系统
    制造运营管理 (MOM) 的工作流驱动方法
    语义模型在智能工业运营中的作用
    定义运营系统架构
    在离散混合制造环境中应用制造运营模型
    面试官:如果存取IP地址,用什么数据类型比较好 (C#版本)
    使用WtmPlus低代码平台提高生产力
  • 原文地址:https://www.cnblogs.com/weiweishuo/p/3082642.html
Copyright © 2011-2022 走看看