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