保护模式编程、六

【异常和中断】:

异常和中断的处理是通过一个中断向量表对应起来的,这样做的目标是能明确发生特殊转移时候能判断是什么异常或者中断并做出相应的处理。

IRQ0-IRQ19 已经定义好了.IRQ20-IRQ31是INTEL预留的向量,我们不去使用它。

IRQ32-IRQ255是用户自定义中断,那么我可以将自己的定义的中断与这些中断向量号联系起来。

1、异常:

异常是指程序在运行中所产生的。比如div 0,保护违例、页错误等。

异常是分3种:

㈠、FALTS

它是属于错误、故障类型的异常,再此异常发生后,CPU会将当前EIP压栈。等异常处理完毕后。继续再执行一遍引发异常的当前代码行.

㈡、Traps

它是属于陷阱异常,在此异常发生后,CPU会将EIP+1也就是下一条指令的位置压栈.等异常处理完毕后,继续执行下一条指令/

㈢、Abort

它属于严重性异常,在此异常发生后,不允许程序继续执行,用来报告严重错误的.

那么简单的就是分这三类 错误(FALTS)、陷阱(TRAPS)、ABORT(终止)。

2、中断:

中断分两种:外部中断、INT N中断:

外部中断是由外围设备硬件随机产生的,他们通常用来处理处理器外部的事件。比如外围设备的请求。软件通过执行int n指令也可以产生中断.

㈠、外部中断:

外部中断又分为不可屏蔽中断(NMI)、与可屏蔽中断之分。分别用CPU的两根引脚来接收。其中NMI引脚接收不可屏蔽的中断信号,之所以它是不可屏蔽中断,因为它与EFLAGS标志寄存器的IF位无关。NMI与8259A可编程控制器无关。 它由NMI引脚接收。

INTR引脚接收可屏蔽中断信号。因为它要求判断eflags 的IF位.可屏蔽中断是由(8259A)可编程控制器连系起来的.

8259A可编程控制给外围设备与CPU的中断向量起到一个代理的作用,8259A可编程控制器它是两片级联,的也就是分主8259A与从8259A两片。每个片包含8个中断向量号。所以他可以链接到15个外围设备。其中主8259A的IRQ2向量对应的就是从8259A。所以只能处理15个外围设备。在BIOS初始化它的时候IRQ0-IRQ7被设置为对应的向量号08h-0fh,而这写向量号在保护模式是已被CPU使用的。所以我们必需重新设置一下8259A对应的向量号。

设置8259A的方法:

1、往端口20h(主)或端口A0h(从)写入ICW1(初始化命令文本) 控制需要ICW4、并且是ICW必需写10h

2、往端口21h(主)或端口A1h(从)写入ICW2(初始化命令文本) 写主中断、从中断向量号的基号.

3、往端口21h(主)或端口A1h(从)写入ICW3(初始化命令文本)主中断号与从8259A对应

4、往端口21h(主)或端口A1h(从)写入ICW4(初始化命令文本) 主从模式

5、最后可做的屏蔽主从8259A中断.

就这些步骤:

1、通常把11h(ICW1)写入到20H(主)、A0h(从):

                        1表示需要ICW4,并且如果是写ICW1必需要10H,所以要写11h

2、把20h(ICW2)写入到21h(主),28h写入到A0h(从):

                          20h代表向量号.写到主8259A的IRQ0位置、28h代表向量号,写到从8259A的IRQ8位置。

3、把04h写入21h(主),02写入到A1h(从):

                      04h表示主的IRQ2对应从8259A,02h表示从片连的主片的IRQ。

4、把1h写到21h(主)、1h写入到A1h(从):

             1h表示主8259A80X86模式、01H表示从8259A80X86模式。

5、把0FF写到21h(主)、0ffh写入到A1h(从):

屏蔽所有中断。这次写的不是ICW而是OCW,OCW分两中情况:

一种是屏蔽或打开中断,发生EOI给8259A以通知它中断处理结束。

屏蔽中断只需写入OCW1 主从8259A对应的IRQ 如果位数是0表示开始某个中断、如果置1表示关闭某个中断。 其中主8个IRQ0-IRQ7 所以FFH 关闭所有.从也是8个IRQ8-IRQ15置1关闭0ffh。

实际上OCW1是被写入了中断屏蔽寄存器(IMR)中.当一个中断到达,IMR会判断此中断是否应被丢弃。

EOI是中断处理结束后需要发送的,EOI同常需要想主20H或从A0H端口发送OCW2来完成的。

mov    al,20h

out     20h或A0h,al ;完成中断处理

三、IDT(Interrupt Descriptor Table )中断描述符表

使用IDT将这些中断向量号对应到具体的代码处理上去:

IDT有:中断描述符(int )、陷阱描述符(Traps)、任务描述符三种:

现在就来定义一个中断向量结构体,因为向量号最多也就是0-255。那么就这样定义:

[Section .itd]

LABEL_IDT:

%rep      128;重复指令只支持128个

           Gate      SelectorCode32,SpuriousHanlde,0,DA_386IGate ;使所以向量号都对应Coe32的为Sp偏移处理位置。

%endrep

.80h:   Gate SelectorCode32,SpuriousHandle,0,DA_386IGate    ;.80h是Flag标志

IdtLen      equ $ - LABEL_LDT

IdtPtr       dw        IdtLen - 1            ;此定义与GDT飞车类似.

                dd        0

定义完成后就加载它:

加载之前要吧IdtPtr的 dd 0 改成IDT物理基地址,然后加载:

lidt         [IdtPtr]

int 80h调用中断。

在运行中断程序后Int 21h已经无法变成回DOS的中断了,。,因为我们修改了8259A的IRQ值。

这个时候就需要改回来。那么继续重复设置8259A的步骤不过参数不同而已

1、ICW1的内容17h:

       2h表示单个主8259 A,所以实模式只有128的向量号。

     1h表示需要ICW4、 ICW1必需10h 、4h表示4字节中断向量。0h表示8字节描述符中断向量。

2、ICW2的内容08h:

将主8259A的 IRQ0 对应IRQ8H向量号,DOS时代的IRQ8

3、ICW4的内容1h;

表示80X86模式:

4、恢复中断屏蔽寄存器IMR的原值

mov al, [fs:SavedIMREG] ;

out 021h, al   ;
call io_delay ;操作延迟等待操作的完成。4个nop指令

我们改变了8259A原理DOS状态的值。,需要在DOS的时候记录下来:

1、DOS,IDTR寄存器的状态

2、DOS、IMR屏蔽与否寄存器的状态。

这样我们在保护模式数据段中定义两个变量来保存它们的值。

_SavedIMREG db 0

_SavedIDTR db 0

在用litd 加载IDT之前要先用sidt [SavedIDTR]取出IDTR的内容. 要注意SavedIDTR要是64位

并且保存中断屏蔽寄存器的值 in al,21h

mov [SaveImr],al

这样 在回DOS之前就可以恢复DOS的中断IDTR寄存器 与 IMR屏蔽寄存器了

但是如果你引用了8259A外部设备中断,那么还需要恢复DOS时候的8259A状态也就是一个主片

五、中断注意的:

弄清楚一些指令和标志:

通过中断调用门进行中断时,会将IF关闭,以达到不被其他程序打扰作用。而陷阱门不会改变IF位所以有可能被其他的中断所打扰。

I/O特权标志IOPL(I/O Privilege Level) 它是eFlags的IOPL两位.只有当CPL为0时IOPL域才会改变。

1:ret、retn、retf:

ret是过程返回,是根据当前段的属性判断是近返回还是远返回。

retn指定返回方式是近返回 pop eip

retf指定返回方式是远返回 pop eip 、pop cs

2:iret 、iretw 、iretd:

iret无所谓近远之分 因为它必需 调用中断的时候是push eflags push cs push eip 、如果是系统中断那么会有错误码push codeerr 在返回前要先清掉codeerr

iret 会根据会自动的判断返回是ip 还是eip.

iretw 显示性的返回 ip

iretd 显示性的返回 eip eFlags

用中断的时候要搞清楚两种中断:

1、NMI引脚的中断它是接收不可屏蔽的中断,

2、INTR引脚是可屏蔽中断,其中它是根据8259A可编程控制器来代理中断的。它是外设备中断。

用int n中断属于软中断仅判断 EFlags的 IF位来判断是否屏蔽。

而外设备还要通过8259A的IMR 中断屏蔽寄存器状态来判断。它可以表示IRQ0-IRQ7的中断是否屏蔽。其中IRQ2又级连从8259A的IRQ8-IRQ15的。访问IRQ2就等于访问IRQ9

所以如果想屏蔽外部设备8259A的中断 必需 IF还有 OCW1也就是IMR寄存器。

六:保护模式下的I/O特权:

1、IOPL在eFlags 状态标志寄存器的 12-13位,IO特权的关键位。

指令in ,ins ,out,outs,cli,sti 只有在CPL<=IOPL的情况下才能进行。这些指令是I/O的敏感指令。

所以只能在CPL<=IOPL的情况下才能正常访问。

popfd iretd也可以是可以改变eFlags的。不过必需CPL<=IOPL。

2、I/O许可位图:

它存放在以TSS段为基址的段里,从指定的I/O基址开始 的数据是按位判断的。

也就是说

tss{

     dw   0;调式陷阱标志

   dw    $ - LABEL_TSS + 2;指向I/O许可位图的基地址

db      ffh       ;第一个I/O位图是0FFh 那么它变成11111111b 表示端口0h - 7h.其中它全为1表示都可以用

db 10h      ;第二个许可位图数据01h 那么它合并第一个表示11111111 00010000b,加在一起有16个端口了.0h-15h 但是其中8-10跟12-15都是0那么 8h端口-Ah端口不能用 ,0ch-0fh不能用

db 0ffh ;结束标志

}

接下来继续Study

总结】:

1、异常

异常简单的分为三种FALTS(错误)、TRAPS(陷阱) ,ABORT(终止)。

2、中断

中断是指外部设备产生的中断请求:而外部中断分为不可屏蔽(NMI引脚)和可屏蔽中断(INTR引脚)。

这里着重将了INTR的可屏蔽中断,要用到8259A可编程控制器,

使用它主要要首先向主片20h端口写ICW1和从片A0H端口ICW1,再向主片21h端口和从片A1端口写ICW2,再向主片21h端口和从片A1端口写ICW3,再向主片21h端口和从片A1端口写ICW4。

最后可以向21h端口写入是否屏蔽中断OCW1,OCW2是想主20H或从A0端口写入20H表示中断处理完成.

  中断向量与中断向量表
  在中断源识别方法时提到:早期的微机系统中将由硬件产生的中断标识码
(中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址)称为中断向量。在Pc/AT中也用到这个名称,但含义有所不同。在Pc/AT机中,中断向量是指中断服务程序的入口地址,包括段地址CS和段内偏移 量IP共4个字节。在PC/AT中,规定内存储器的最低1 KB用来存放中断向量(共256个),称这一片内存区为中断向量表,如图所示。
  在Pc/AT中由硬件产生的中断标识码被称为中断类型号(当然,中断类型号还有其他的产生方法,如指令中直接给出、CPU自动形成等),即在中断响应期间8259A产生的是当前请求中断的最高优先级的中断源的中断类型号。中断类型号和中断向量之间有下面的关系:
  中断类型号×4=存放中断向量的首地址
  有了存放中断向量的首地址,从该地址开始的4个存储单元中取出的就是中断服务程序的入口

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭