1、段基地址(BIT24-31)Desc ENDS伪描述符结构类型定义(用于装入全局或中断描述符表寄存器)PDesc STRUCLimit DW 0 ;16位界限Base DD 0 ;32位基地址PDesc ENDS门描述符结构类型定义Gate STRUCOffsetL DW 0 ;32位偏移的低16位Selector DW 0 ;选择子DCount DB 0 ;双字计数GType DB 0 ;类型OffsetH DW 0 ;32位偏移的高16位Gate ENDS存储段描述符类型值说明ATDR EQU 90h ;存在的只读数据段类型值ATDW EQU 92h ;存在的可读写数据段属性值ATDWA
2、EQU 93h ;存在的已访问可读写数据段类型值ATCE EQU 98h ;存在的只执行代码段属性值ATCER EQU 9ah ;存在的可执行可读代码段属性值ATCCO EQU 9ch ;存在的只执行一致代码段属性值ATCCOR EQU 9eh ;存在的可执行可读一致代码段属性值DA_386IGate EQU 8Eh ;386 中断门类型值DSEG SEGMENT USE16 ;16位数据段_SavedIMREG_M db 0 ; 中断屏蔽寄存器值_SavedIMREG_S db 0 ; DB 512 dup (0)TopOfStack LABEL BYTEGDT LABEL BYTE ;全局
3、描述符表DUMMY Desc ;空描述符Code Desc 代码段描述符DataV Desc 源数据段描述符DataP Desc 目标数据段描述符Code32 Desc GDTLen = $-GDT ;全局描述符表长度VGDTR PDesc 伪描述符Code_Sel = Code-GDT ;代码段选择子DataV_Sel = DataV-GDT ;源数据段选择子DataP_Sel = DataP-GDT ;目标数据段选择子Code32_Sel = Code32-GDT ; IDTALIGN 32IDT LABEL BYTEIDT_00_1F Gate 32 dup ()IDT_20 Gate
4、1 dup (IDT_21 Gate 1 dup () ;IDT_21_7F Gate 94 dup (IDT_80 Gate 1 dup (IDTLen = $-IDT ;中断描述符表长度VIDTR PDesc _wSSValueInRealMode dw 0_wSPValueInRealMode dw 0_SavedIDTR dd 0 ; 用于保存 IDTR dd 0DSEG ENDS ;数据段定义结束打开A20地址线EnableA20 MACRO push ax in al,92h or al,00000010b out 92h,al pop ax ENDM关闭A20地址线Disable
5、A20 MACRO and al,11111101b16位偏移的段间直接转移指令的宏定义(在16位代码段中使用)JUMP16 MACRO Selector,Offset DB 0eah ;操作码 DW Offset ;16位偏移量 DW Selector ;段值或段选择子CSEG SEGMENT USE16 ;16位代码段 ASSUME CS:CSEG,DS:DSEGStart PROC mov ax,DSEG mov ds,ax mov _wSSValueInRealMode,ss ;堆栈段 mov _wSPValueInRealMode,sp ;堆栈指针 准备要加载到GDTR的伪描述符 m
6、ov bx,16 mul bx add ax,OFFSET GDT ;计算并设置基地址 adc dx,0 ;界限已在定义时设置好 mov WORD PTR VGDTR.Base,ax mov WORD PTR VGDTR.Base+2,dx准备要加载到IDTR的伪描述符 mov ax,SEG IDT add ax,OFFSET IDT ; mov WORD PTR VIDTR.Base,ax mov WORD PTR VIDTR.Base+2,dx设置代码段描述符 mov ax,cs mov WORD PTR Code.BaseL,ax ;代码段开始偏移为0 mov BYTE PTR Code
7、.BaseM,dl ;代码段界限已在定义时设置好 mov BYTE PTR Code.BaseH,dh mov ax,seg SpuriousHandler mov WORD PTR Code32.BaseL,ax ; mov BYTE PTR Code32.BaseM,dl ; mov BYTE PTR Code32.BaseH,dh mov ax,8000h mov dx,000BH mov WORD PTR DataV.BaseL,ax mov BYTE PTR DataV.BaseM,dl mov BYTE PTR DataV.BaseH,dh设置目标数据段描述符 mov ax,ds
8、mul bx ;计算并设置目标数据段基址 mov WORD PTR DataP.BaseL,ax mov BYTE PTR DataP.BaseM,dl mov BYTE PTR DataP.BaseH,dh ; 保存中断屏蔽寄存器(IMREG)值 in al, 21h mov _SavedIMREG_M, al ;主片IMR=21h in al, 0A1h mov _SavedIMREG_S, al ;从片IMR=A1h 保存 IDTR sidt QWORD PTR _SavedIDTR加载GDTR lgdt QWORD PTR VGDTR cli ;关中断 EnableA20 ;打开地址线
9、A20 lidt QWORD PTR VIDTR ;加载IDT切换到保护方式 mov eax,cr0 or eax,1 mov cr0,eax清指令预取队列,并真正进入保护方式 JUMP16 Code_Sel,Virtual:现在开始在保护方式下运行 mov ax,DataV_Sel mov gs,ax ;加载源数据段描述符 mov ax,DataP_Sel mov ds,ax ; mov ss,ax ; 堆栈段选择子 mov sp,offset TopOfStack call Init8259A mov ah, 0Ch ; 0000 黑底 1100 红字 mov al, ! mov gs:(
10、80 * 0 + 72) * 2), ax ; 屏幕第 0 行, 第 72 列。 x: jmp x int 080h sti mov ebx,0 xor ecx,ecxWaitLoop: cmp ebx, 100jb WaitLoop cmp ecx,1 ;等到Esc jnz WaitLoop cli call SetRealmode8259A切换回实模式 and al,11111110b清指令预取队列,进入实方式 JUMP16 , Init8259A -Init8259A: mov al, 011h out 020h, al ; 主8259, ICW1. call io_delay out
11、0A0h, al ; 从8259, ICW1. mov al, 020h ; IRQ0 对应中断向量 0x20 out 021h, al ; 主8259, ICW2. mov al, 028h ; IRQ8 对应中断向量 0x28 out 0A1h, al ; 从8259, ICW2. mov al, 004h ; IR2 对应从8259 主8259, ICW3. mov al, 002h ; 对应主8259的 IR2 从8259, ICW3. mov al, 001h 主8259, ICW4. 从8259, ICW4. mov al, 11111100b ; 主8259, OCW1. mov
12、 al, 11111111b ; 屏蔽从8259所有中断 从8259, OCW1. ret SetRealmode8259A -SetRealmode8259A: mov al, 08h ; mov al, 70h ; mov al, _SavedIMREG_M ; 恢复中断屏蔽寄存器(IMREG)的原值 out 021h, al ;mov al, _SavedIMREG_S ;out 0A1h, al ;call io_delayio_delay: nopReal:现在又回到实方式 DisableA20 lidt QWORD PTR _SavedIDTR mov ss,_wSSValueIn
13、RealMode mov sp,_wSPValueInRealMode sti mov ax,4c00h int 21hStart ENDPCSEG ENDS ;代码段定义结束CSEG32 SEGMENT USE32 interrupt handler -ASSUME CS:CSEG32,DS:ClockHandler: inc ebx inc byte ptr gs:(80 * 0 + 70) * 2) ; 屏幕第 0 行, 第 70 列。 mov al, 20h out 20h, al ; 发送 EOI iretdEscHandler:键盘中断服务程序,用来在屏幕第 1 行, 第 70 列
14、显示响按键的不断跳动的字符 in al,60h cmp al,1 jnz Nesc mov ecx,1Nesc:(80*1+70)*2) mov al,20h out 20h,alUserIntHandler: mov ah, 0Ch ; mov al, I mov gs:(80 * 0 + 71) * 2), ax ; 屏幕第 0 行, 第 71 列。SpuriousHandler: -CSEG32 ENDS END Start此代码在原先老师所给的代码基础上做了如下的修改:加入esc的中断处理 in al,60h out 20h,al ;如果键入非esc建则在第二行加一显示字符五 实验结果刚开始运行时在屏幕的第一行第70列字符ASCLL码加一并显示,实现字符的跳动.当输入非esc键时在屏幕的第二行第70列字符ASCLL码加一并显示当输入esc键时退出循环.六 心得体会1、键入非ESC键时,运行时发现按下一次后ascll码却加了2,因为程序中设计成非esc键入就加一,因此是键盘按下时发出一个信号,键盘弹回时又发出一个信号,致使ASCLL码加了两次.2、通过实验对8259的初始化有了新的认识,对两片8259A的级联有了具体的了解.3、又重新翻了一遍接口的教材,对全局描述符表GDT,中断
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1