Add interrupts module: INT 3 (CC breakpoint) vs INT 21h (DOS services)
NASM sources, DOSBox/FreeDOS Debug/Unicorn harness, captured output and 31 assertions backing the ankurm.com article "INT 3 vs INT 21h in 8086 Assembly". Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
; int3_handler.asm -- install our own INT 3 handler (AH=25h), then trigger it twice:
|
||||
; once with the one-byte CC and once with the two-byte CD 03.
|
||||
; Prints how far past the trapping instruction the pushed return IP points, and the
|
||||
; state of IF (interrupt flag) inside the handler versus after IRET.
|
||||
bits 16
|
||||
org 0x100
|
||||
; --- save the old vector with AH=35h, install ours with AH=25h ---
|
||||
mov ax, 3503h
|
||||
int 21h ; ES:BX = current INT 3 handler
|
||||
mov [old_off], bx
|
||||
mov [old_seg], es
|
||||
mov ax, 2503h
|
||||
mov dx, handler
|
||||
int 21h ; DS:DX = new handler for vector 3
|
||||
|
||||
sti ; make sure IF=1 before we trap, so the handler's IF=0 is visible
|
||||
mov word [target], trap_cc
|
||||
mov dx, m_cc
|
||||
call puts
|
||||
trap_cc:
|
||||
int3 ; CC
|
||||
call report
|
||||
|
||||
mov word [target], trap_cd
|
||||
mov dx, m_cd
|
||||
call puts
|
||||
trap_cd:
|
||||
db 0CDh, 03h ; CD 03
|
||||
call report
|
||||
|
||||
; --- restore the old vector and exit ---
|
||||
push ds
|
||||
mov dx, [old_off]
|
||||
mov ds, [old_seg]
|
||||
mov ax, 2503h
|
||||
int 21h
|
||||
pop ds
|
||||
mov ax, 4C00h
|
||||
int 21h
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; The handler runs with IF=0 and TF=0 (the CPU cleared them when it took the interrupt).
|
||||
handler:
|
||||
push bp
|
||||
mov bp, sp
|
||||
push ax
|
||||
; stack now: [bp+0]=saved BP, [bp+2]=return IP, [bp+4]=return CS, [bp+6]=FLAGS
|
||||
mov ax, [bp+2]
|
||||
mov [ret_ip], ax
|
||||
mov ax, [bp+6]
|
||||
mov [flags_pushed], ax
|
||||
pushf
|
||||
pop ax ; FLAGS as the handler itself sees them
|
||||
mov [flags_inside], ax
|
||||
pop ax
|
||||
pop bp
|
||||
iret
|
||||
|
||||
report:
|
||||
mov dx, m_delta
|
||||
call puts
|
||||
mov ax, [ret_ip]
|
||||
sub ax, [target] ; how many bytes past the trapping instruction?
|
||||
call putdec
|
||||
mov dx, m_ifpush
|
||||
call puts
|
||||
mov ax, [flags_pushed]
|
||||
mov cl, 9
|
||||
shr ax, cl
|
||||
and al, 1
|
||||
add al, '0'
|
||||
mov dl, al
|
||||
mov ah, 02h
|
||||
int 21h
|
||||
mov dx, m_ifin
|
||||
call puts
|
||||
mov ax, [flags_inside]
|
||||
mov cl, 9
|
||||
shr ax, cl
|
||||
and al, 1
|
||||
add al, '0'
|
||||
mov dl, al
|
||||
mov ah, 02h
|
||||
int 21h
|
||||
mov dx, m_tfin
|
||||
call puts
|
||||
mov ax, [flags_inside]
|
||||
mov cl, 8
|
||||
shr ax, cl
|
||||
and al, 1
|
||||
add al, '0'
|
||||
mov dl, al
|
||||
mov ah, 02h
|
||||
int 21h
|
||||
mov dx, m_ifafter
|
||||
call puts
|
||||
pushf
|
||||
pop ax
|
||||
mov cl, 9
|
||||
shr ax, cl
|
||||
and al, 1
|
||||
add al, '0'
|
||||
mov dl, al
|
||||
mov ah, 02h
|
||||
int 21h
|
||||
jmp crlf
|
||||
|
||||
m_cc db 'CC (INT3): $'
|
||||
m_cd db 'CD 03 (INT 3): $'
|
||||
m_delta db 'return IP = trap address + $'
|
||||
m_ifpush db ', IF pushed = $'
|
||||
m_ifin db ', IF in handler = $'
|
||||
m_tfin db ', TF in handler = $'
|
||||
m_ifafter db ', IF after IRET = $'
|
||||
|
||||
old_off dw 0
|
||||
old_seg dw 0
|
||||
target dw 0
|
||||
ret_ip dw 0
|
||||
flags_pushed dw 0
|
||||
flags_inside dw 0
|
||||
|
||||
%include "common.inc"
|
||||
Reference in New Issue
Block a user