One, 80386, memory, 8259A connection as shown in Figure 1
Figure 1
II. Programming 8259A Interrupt Controller (writes ICW to a specific register)
The 8259A is a programmable interrupt controller, and its settings are not complex and are implemented by writing a specific ICW (initialization Command Word) to the corresponding port. The main 8259A corresponding port address is 20h and 21h, the corresponding port address from 8259A is a0h and a1h. ICW a total of 4, each with a specific format of bytes, in order to initialize the process of 8259A to have a general understanding, we will later to pay attention to each of the ICW format, now, first look at the initialization process:
1. Write ICW1 to Port 20h (main slice) or a0h (from slice).
2. Write ICW2 to Port 21h (main slice) or a1h (from slice).
3. Write ICW3 to Port 21h (main slice) or a1h (from slice).
4. Write ICW4 to Port 21h (main slice) or a1h (from slice).
ICW format as shown in Figure 2:
Figure 2 ICW format Figure 3 OCW1
If you want to block or open an external interrupt, you only need to write OCW1 to 8259A, that is, write interrupt screen register (IMR), OCW1 format as shown in Figure 3.
The difference between a masked interrupt and an NMI is whether it is affected by the if bit, while the 8259A Interrupt screen register (IMR) also affects whether the interrupt is being responded to. Therefore, the occurrence of an externally masked interrupt can be affected by two factors, only if the IF bit is 1 and the corresponding bit of IMR is 0 o'clock. Except for single-step interrupts, all internal interrupts cannot be disabled, that is, the if=0 cannot be made to respond by CLI directives.
Iii. interrupts in protected mode
1, 0-19 of interrupts and anomalies have been arranged, such as the Book 89 page Table 3.8
2. When there is a privileged level change, the interrupt stack changes as shown in Figure 4. The instruction iretd must be used when returning from an interrupt or an exception, which is similar to RET, except that it changes the value of eflags at the same time. It is important to note that only if the CPL is 0 o'clock, the IOPL field in EFlags will change, and if the CPL is less than or equal to IOPL, the if will be changed. In addition, the error code is not automatically ejected from the stack when iretd executes, so it is removed from the stack before executing it. instruction in, ins, out, outs, CLI, STI can only be executed if the CPL is less than or equal to IOPL. These directives are referred to as I/O sensitive directives. If a low-privileged instruction attempts to access these I/O sensitive instructions will cause a general protection error (#GP).
Figure 4 Stack when an interrupt or exception occurs
3. I/O license bit
A TSS offset of 102 bytes has a thing called an I/O license bitmap base, which is an offset from the address of the TSS, which points to the I/O license bitmap. The bitmap is called because each of its ports indicates whether a byte port address is available. If one is 0, the port number corresponding to this bit is available, and 1 is not available. Since each task can have a separate TSS, each task can have its own I/O license bitmap.
4. Interrupt execution during protection mode
The following hardware is done automatically:
① gets the interrupt type code from the interrupt message.
The value of the ② flag register eflags into the stack, because the value of the flag register is changed during the break, so it is saved in the stack first.
③ sets the flag register if and TF bits to 0, in order to prevent additional external interrupts from being interrupted in this interrupt.
④cs,eip,error code into the stack.
The ⑤ finds the interrupt gate execution code in IDT based on the interrupt type code.
The iretd command pops up a 32-bit EIP value, then pops up a 32-bit value and passes the lowest 2-byte value into the CS register, and then pops up a 32-bit flag register value.
The PMTEST9.ASM code is as follows:
%include "Pm.inc"; constants, macros, and some descriptions of org 07c00h jmp label_begin [section. GDT]; GDT; Segment base, segment bounds, attributes Label_gdt:descriptor 0, 0, 0; Null descriptor Label_desc_normal:descriptor 0, 0FFFFH, DA_DRW; Normal Descriptor Label_desc_code32:descriptor 0, segcode32len-1, Da_c + da_32; Non-Uniform code snippet Label_desc_code16:descriptor 0, 0FFFFH, Da_c; Non-Uniform code snippet, Label_desc_video:descriptor 0b8000h, 0FFFFH, DA_DRW; Memory first address; GDT ends Gdtlen equ $-LABEL_GDT; GDT length gdtptr DW GdtLen-1; GDT limit DD 0; GDT base Site; GDT Selector Sub Selectornormal equ label_desc_normal-label_gdt SelectorCode32 equ LABEL_DESC_CODE32-LABEL_GDT SelectorCode16 Equ Label_desc_code16-label_gdt selectorvideo equ Label_desc_video-label_gdt; END of [section. GDT] [section. data1]; Data section ALIGN [BITS] Label_data:; The use of these symbols in real mode; Variable _wspvalueinrealmode DW 0 _savedidtr:dd 0; For saving IDTR DD 0 _savedimreG:db 0; Interrupt mask Register Value datalen equ $-label_data; END of [section. Data1]; IDT [section. IDT] ALIGN [BITS] Label_idt: Up to 256 interrupt gates, each accounting for 8 bytes, so IDT accounts for up to 2K. The first 20 have been occupied.; Gate target selector, offset, DCount, attribute%rep gate SelectorCode32, Spurioushandler, 0, D A_386igate%endrep 020h:gate SelectorCode32, Clockhandler, 0, da_386igate; Convert to 10-in-one%rep Code32, Spurioushandler, 0, da_386igate%endrep. 080h:gate SelectorCode32, Userinthandler, 0, da_386igate; conversion For 10 binary is Idtlen equ $-Label_idt idtptr DW IdtLen-1; Segment limit DD 0; Base site; END of [section: IDT] [section. s16] [BITS] Label_begin:mov ax, CS mov ds, ax mov es, AX mov ss, ax mov sp, 0100 H mov [label_go_back_to_real+3], AX mov [_wspvalueinrealmode], SP; Initialize 16-bit code Snippet descriptor mov ax, CS movzx eax, ax SHL eax, 4 add eax, LABEL_SEG_CODE16 mov word [Label_desc_code16 + 2], ax;d s : Label_desc_code16 shr eax, mov byte [label_desc_code16+ 4], AL mov byte [label_desc_code16 + 7], ah; Initialize 32-bit code snippet Descriptor xor eax, EAX mov ax, cs shl eax, 4 add eax, LABEL_SEG_CODE32 mov word [label_desc_code32 + 2], ax SHR EAX, MOV byte [Label_desc_code32 + 4], AL mov byte [label_desc_code32 + 7], ah; Prepare for loading GDTR xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_GDT; EAX <-GDT Base Address mov DWORD [gdtptr + 2], eax; [Gdtptr + 2] <-GDT base site; Prepare for loading IDTR xor eax, eax mov ax, ds shl eax, 4 add eax, Label_idt; EAX <-IDT Base Address mov DWORD [idtptr + 2], eax; [Idtptr + 2] <-IDT base site; Save IDTR Sidt [_SAVEDIDTR]; Save the value of the IDTR register to DS:_SAVEDIDTR; Save Interrupt Mask Register (IMREG) value in AL, 21h mov [_savedimreg], AL; Load GDTR LGDT [gdtptr]; Off interrupt cli, int 80h can function, but can be shielded interrupt (through 8255 set) can not respond to the if=0; Load IDTR Lidt [idtptr]; Open Address line A20 in Al, 92h or Al, 00000010b out 92h, AL; Ready to switch to protected mode mov eax, CR0 or eax, 1 mov cr0, eax; Real access to protected mode in JMP DWORD selectorcode32:0; The execution of this sentence will be loaded into CS SelectorCode32; and jump to Code32selector:0 Office label_real_entry:; Jump back from Protected mode to real mode on to here MOV ax, CS mov ds, ax mov es, AX mov ss, ax mov sp, [_wspvalueinrealmode] Lidt [_SAVEDIDTR]; Restores the original value of IDTR mov al, [_savedimreg]; ┓ Recovery Interrupt screen Register (IMREG) The original value out 21h, AL; ┛in al, 92h; ┓and al, 11111101b; ┣ off A20 Address line out 92H, AL; ┛sti; Open Interrupt mov ax, 4c00h; ┓int 21h; ┛ back to DOS; END of [section. s16] [section. S32]; 32-bit code snippet.
Jumped in by real mode.
[BITS 32] Label_seg_code32:mov ax, Selectorvideo mov gs, ax; Video Segment Selector (purpose) call init8259a int 080h; interrupt, similar to calling STI; After an interrupt, the clock interrupt begins to take effect if=1 JMP $; To demonstrate the results, remove and then jump back to real mode called SetRealmode8259 A To stop jmp selectorcode16:0;
init8259a--------------------------------------------------------------------------------------------- Init8259a:mov al, 011hn; 00010001 out 020h, AL;
Lord 8259, ICW1. Call Io_delay out 0a0h, AL;
From 8259, ICW1. Call Io_delay mov al, 020h; IRQ0 corresponds to interrupt vector 0x20 00100000 because the first 0-19 interrupts have been accounted for out 021h, AL;
Lord 8259, ICW2. Call Io_delay mov al, 028h; IRQ8 corresponds to interrupt vector 0x28 00101000 out 0a1h, AL;
From 8259, ICW2. Call Io_delay mov al, 004h; IR2 should be 8259 00000100 out 021h, AL;
Lord 8259, ICW3. Call Io_delay mov al, 002h; Corresponding to the main 8259 IR2 0000 0010 out 0a1h, AL;
From 8259, ICW3. Call Io_delay mov al, 001h 0000 0001 out 021h, AL;
Lord 8259, ICW4. Call Io_delay out 0a1h, AL;
From 8259, ICW4. Call Io_delay; Mov al, 11111111b; Shield Master 8259 all interrupts mov al, 11111110b; Just turn on the timer interrupt, the external can be shielded interrupt only in the if=1 and IMR corresponding bit is 0 o'clock response out 021h, AL;
Lord 8259, OCW1. Call Io_delay mov al, 11111111b; Shielded from 8259 all interrupts out 0a1h, AL;
From 8259, OCW1. Call Io_delay ret; init8259a---------------------------------------------------------------------------------------------;
setrealmode8259a--------------------------------------------------------------------------------------------- Setrealmode8259a:mov al, 017h 0001 0111 out 020h, AL;
Lord 8259, ICW1. Call Io_delay; 4 byte interrupt vector, single 8259 mov al, 008h; IRQ0 corresponding interrupt vector 0x8 out 021h, AL;
Lord 8259, ICW2.
Call Io_delay; ICW3 has no need for Mov al, 001hOut 021h, AL;
Lord 8259, ICW4. Call Io_delay ret;
setrealmode8259a--------------------------------------------------------------------------------------------- Io_delay:nop NOP NOP NOP ret; int handler---------------------------------------------------------------_clockhandler:clockhandler equ _ Clockhandler-$$ Inc Byte [GS: ((80 * 0 + 70) * 2)];
Screen No. 0, column 70th. mov al, 20h out 20h, AL; Send EOI iretd; iretd command pops up a 32-bit EIP value, then pops up a 32-bit value and passes the lowest 2 byte value to the CS register, and finally pops up a 32-bit flag register value _userinthandler:userintha Ndler equ _userinthandler-$$ mov ah, 0Ch; 0000: Black Bottom 1100: Red Word mov al, ' I ' mov [GS: ((+ * 0 +) * 2)], ax;
Screen No. 0, column 70th. iretd _spurioushandler:spurioushandler equ _spurioushandler-$$ mov ah, 0Ch;
0000: Black Bottom 1100: Red Word mov al, '! ' mov [GS: ((0 * + +) * 2)], ax;
Screen No. 0, column 75th. JMP $ iretd; ---------------------------------------------------------------------------Segcode32len equ $-label_seg_code32; END of [section. S32]
; 16-bit code snippet. Jumped in from a 32-bit code snippet and jumped out into real mode [section. s16code] ALIGN [BITS] Label_seg_code16:; Jump back to Real mode: mov ax, selectornormal mov ds, ax mov es, AX mov fs, AX MOV gs, AX mov ss, ax mov eax, CR0 and Al, 1111111 0B mov cr0, eax label_go_back_to_real:jmp 0:label_real_entry; The segment address is set to the correct value at the beginning of the program Code16len equ $-label_seg_code16; END of [section. S16code]