Files
8086-Programs/interrupts/asm/int3_handler.asm
T
asmhatreandClaude Sonnet 5.5 09af523f8c 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
2026-09-30 19:10:56 +00:00

124 lines
2.7 KiB
NASM

; 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"