如何用TASM在8086中实现带优先级的PDP11风格硬件中断?
8086 TASM Interrupt Priority Implementation Example
Got it, let's walk through a complete, runnable TASM example that meets your requirements: a low-priority default execution routine, a higher-priority keyboard interrupt handler, and the highest-priority system clock interrupt handler. This uses standard 8086 interrupt mechanics and preserves compatibility with original BIOS routines.
Key Background
The 8086 hardware interrupt priority is fixed for IRQs:
- IRQ0 (Clock, INT 08h) → Highest priority
- IRQ1 (Keyboard, INT 09h) → Next highest
- Main program (default routine) → Lowest priority (gets interrupted by any IRQ)
We'll replace the default INT 08h and INT 09h vectors with custom handlers, while saving the original vectors so we can chain back to BIOS functionality if needed.
Complete TASM Code
.MODEL SMALL .STACK 100H .DATA ; Strings for output DEFAULT_MSG DB 'Running default routine... $' CLOCK_MSG DB 0Dh, 0Ah, 'Clock interrupt triggered (Highest priority)$' KEYBOARD_MSG DB 0Dh, 0Ah, 'Keyboard interrupt triggered (Medium priority)$' ; Variables to store original interrupt vectors OLD_INT08_OFF DW ? OLD_INT08_SEG DW ? OLD_INT09_OFF DW ? OLD_INT09_SEG DW ? .CODE MAIN PROC ; Initialize data segment MOV AX, @DATA MOV DS, AX ; Save original INT 08h (clock) vector MOV AH, 35h MOV AL, 08h INT 21h MOV OLD_INT08_OFF, BX MOV OLD_INT08_SEG, ES ; Save original INT 09h (keyboard) vector MOV AH, 35h MOV AL, 09h INT 21h MOV OLD_INT09_OFF, BX MOV OLD_INT09_SEG, ES ; Set custom INT 08h handler MOV AH, 25h MOV AL, 08h MOV DX, OFFSET CLOCK_HANDLER PUSH DS MOV DS, CS INT 21h POP DS ; Set custom INT 09h handler MOV AH, 25h MOV AL, 09h MOV DX, OFFSET KEYBOARD_HANDLER PUSH DS MOV DS, CS INT 21h POP DS ; Default execution routine (lowest priority) DEFAULT_LOOP: ; Clear screen and print default message MOV AH, 0Fh INT 10h MOV AH, 00h INT 10h MOV AH, 09h LEA DX, DEFAULT_MSG INT 21h ; Wait a bit (simulate work) MOV CX, 0FFFFh WAIT_LOOP: DEC CX JNZ WAIT_LOOP JMP DEFAULT_LOOP ; Restore original vectors (unreachable in this example, but good practice) RESTORE_VECTORS: MOV AH, 25h MOV AL, 08h MOV DX, OLD_INT08_OFF MOV DS, OLD_INT08_SEG INT 21h MOV AH, 25h MOV AL, 09h MOV DX, OLD_INT09_OFF MOV DS, OLD_INT09_SEG INT 21h ; Exit program MOV AH, 4Ch INT 21h MAIN ENDP ; Highest priority: Clock interrupt handler (INT 08h) CLOCK_HANDLER PROC FAR ; Save registers to stack PUSH AX PUSH DX PUSH DS ; Set data segment MOV AX, @DATA MOV DS, AX ; Print clock interrupt message MOV AH, 09h LEA DX, CLOCK_MSG INT 21h ; Send EOI to PIC (must do to allow future interrupts) MOV AL, 20h OUT 20h, AL ; Call original BIOS clock routine (optional, keeps system time working) PUSH CS POP DS JMP DWORD PTR OLD_INT08_OFF ; Restore registers POP DS POP DX POP AX IRET CLOCK_HANDLER ENDP ; Medium priority: Keyboard interrupt handler (INT 09h) KEYBOARD_HANDLER PROC FAR ; Save registers PUSH AX PUSH DX PUSH DS ; Set data segment MOV AX, @DATA MOV DS, AX ; Read keyboard scan code IN AL, 60h ; Print keyboard interrupt message MOV AH, 09h LEA DX, KEYBOARD_MSG INT 21h ; Send EOI to PIC MOV AL, 20h OUT 20h, AL ; Call original BIOS keyboard routine (handles key echo, etc.) PUSH CS POP DS JMP DWORD PTR OLD_INT09_OFF ; Restore registers POP DS POP DX POP AX IRET KEYBOARD_HANDLER ENDP END MAIN
How to Compile & Run
- Assemble with TASM:
tasm interrupt_priority.asm - Link with TLINK:
tlink interrupt_priority.obj - Run the
.exefile in an 8086 emulator (like DOSBox, Bochs, or VirtualBox with DOS)
Key Explanations
- Interrupt Vector Management: We use
INT 21hfunctions 35h (get vector) and 25h (set vector) to safely replace and restore interrupt handlers without breaking system functionality. - EOI Signal: After handling an interrupt, we send
20hto port20h(PIC master) to tell the hardware we're done—this is critical to allow subsequent interrupts to fire. - Priority Behavior: The clock interrupt (IRQ0) will preempt the keyboard interrupt (IRQ1), and both will preempt the main default routine. You'll see the clock message appear even if the keyboard handler is mid-execution.
- Chaining to BIOS: We call the original BIOS handlers to preserve core system features (like keeping the system clock updated and handling key input echo). You can remove these calls if you want full control over the interrupts.
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

