中断和异常的建立

来源:互联网 发布:耐药监测数据处理软件 编辑:程序博客网 时间:2024/04/30 23:20

中断和异常比较相似,它们的区别是当CPU处理完中断后还会继续执行触发中断后的语句;而异常是CPU在执行时碰到了错误,转而去执行错误处理程序,执行完后,按照异常的不同可能会继续执行触发异常后的第一条语句,也可能会继续执行触发异常的语句或者退出执行。在实模式下,对于中断或异常号和处理程序的对应由中断向量表完成,而在保护模式下,对应由IDT完成。IDT是中断描述符表,即实模式下的中断向量表,在它里面保存的是中断门(TYPE=e),陷阱门(TYPE=f)和任务门(TYPE=5)。

中断分为硬中断和软中断,软中断可以由int指令模拟,int指令也可以模拟异常的发生,它和中断之间的区别是如果用int触发异常,则CPU会保存一个错误码到堆栈,而如果用int指令触发中断,则不会保存错误码。中断执行总的过程是向量号-->IDT-->中断门-->GDT。需要注意的是中断门中低两字节的偏移是对GDT中描述符的基地址而言的,在执行时,CPU会将GDT中段描述符的基地址+中断门偏移地址得到处理程序的地址。

[c-sharp] view plain copy
  1. ;8259A中的IRQ0~IRQ15的中断类型都是固定的  
  2. org 0x7c00  
  3.     mov ax,cs  
  4.     mov ds,ax  
  5.     ;gdt  
  6.     xor eax,eax  
  7.     mov ax,cs  
  8.     shl eax,4  
  9.     add eax,display  
  10.     mov [SEG_CODE+2],ax  
  11.     shr eax,16  
  12.     mov byte [SEG_CODE+4],al  
  13.     mov byte [SEG_CODE+7],ah  
  14.       
  15.     lgdt [gdtr]  
  16.     cli  
  17.     lidt [idtr]  
  18.     mov eax,[idt]  
  19.     mov eax,[idt+4]  
  20.     ;a20  
  21.     in al,0x92  
  22.     or al,00000010b  
  23.     out 0x92,al  
  24.     ;cr0  
  25.     mov eax,cr0  
  26.     or eax,0x1  
  27.     mov cr0,eax  
  28.     call Init8259A  
  29.     int 0x00  
  30. ;创建GDT  
  31. ;========================================================  
  32. gdt:  
  33.     dw 0,0,0,0  
  34.       
  35.     ;代码段  
  36. SEG_CODE:  
  37.     dw 0x07ff  
  38.     dw 0x0000  
  39.     dw 0x9a00  
  40.     dw 0x00cf  
  41.     ;数据段  
  42. SEG_DATA:  
  43.     dw 0x07ff  
  44.     dw 0x0000  
  45.     dw 0x9200  
  46.     dw 0x00cf  
  47. SEG_VIDEO:  
  48.     ;视频段  
  49.     dw 0x07ff  
  50.     dw 0x8000  
  51.     dw 0x920B  
  52.     dw 0x00cf  
  53. gdt_end:  
  54. gdtr:  
  55.     dw gdt_end-gdt-1  
  56.     dw gdt,0  
  57. ;创建IDT  
  58. ;=========================================================  
  59. idt:  
  60.     dw intr_handler-display;不是GDT的选择子 处理程序在代码段中的偏移  
  61.                                                  ;代码段的基地址被赋为display,所以偏移为intr_handler-display  
  62.     dw CODE_SELECTOR;IDT中的选择子都是代码段选择子  
  63.     dw 0x8e00;TYPE=e为中断门  
  64.     dw 0x0000  
  65. idt_end:  
  66. idtr:  
  67.     dw idt_end-idt-1  
  68.     dw idt,0  
  69. ;选择子  
  70. ;==========================================================  
  71. CODE_SELECTOR equ SEG_CODE-gdt  
  72. DATA_SELECTOR equ SEG_DATA-gdt  
  73. VIDEO_SELECTOR equ SEG_VIDEO-gdt  
  74. CALL_GATESELECTOR equ CALL_GATE-gdt  
  75. [BITS 32]  
  76. ;已将display赋给GDT中的代码段描述符  
  77. ;所以代码段的基地址是display的地址  
  78. display:  
  79. mov ax,VIDEO_SELECTOR  
  80. mov gs,ax  
  81. mov ah,0x0c;0000:黑底 1100:红字  
  82. mov al,'A'  
  83. mov edi,(80*0+0)*2  
  84. mov [gs:edi],ax  
  85. jmp $  
  86. ;初始化8259A  
  87. Init8259A:  
  88. mov al,0x11  
  89. out 0x20,al;主片ICW1  
  90. call io_delay  
  91. out 0xA0,al;从片ICW1  
  92. call io_delay  
  93. mov al,0x20  
  94. out 0x21,al;0x21是8259A的主片的另一个端口  
  95. call io_delay  
  96. mov al,0x28  
  97. out 0xA1,al  
  98. call io_delay  
  99. mov al,0x04;IR2(主片中的第三个角连着从片)  
  100. out 0x21,al;ICW3  
  101. call io_delay  
  102. mov al,0x02  
  103. out 0xA1,al  
  104. call io_delay  
  105. mov al,0x01  
  106. out 0x21,al  
  107. call io_delay  
  108. out 0xA1,al  
  109. call io_delay  
  110. mov al,11111111b;主片8259A  
  111. out 0x21,al;OCW1  
  112. call io_delay  
  113. mov al,11111111b;从片8259A  
  114. out 0xA1,al;OCW1  
  115. call io_delay  
  116. ret  
  117. io_delay:  
  118. nop  
  119. nop  
  120. nop  
  121. nop  
  122. ret  
  123. intr_handler:  
  124. mov ax,VIDEO_SELECTOR  
  125. mov gs,ax  
  126. mov ah,0x0c  
  127. mov al,'!'  
  128. mov edi,(80*0+0)*2  
  129. mov [gs:edi],ax  
  130. jmp $  
  131. times 510-($-$) db 0  
  132. dw 0xaa55  
 

上面的代码还没有打开8259A中的中断,如果要打开,则要设置相应的OCW1,如打开时钟中断,则

mov al,11111110b

out 0x21,al

同时,还要用sti指令设置IF=1。

现在还存在的问题是ret指令时,系统总会崩溃,应该是堆栈的问题,所以处理程序最后都死循环了。

0 0
原创粉丝点击