Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Calling INT 21 from typable code
- ; (inspired by https://www.cs.cmu.edu/~tom7/abc)
- ;
- ; The BOUND instruction is very rarely useful, both
- ; because it didn't exist in the original 8086 at all,
- ; and also it is not terribly efficient either. It
- ; compares a register against a structure containing
- ; (signed!) lower and upper bounds, and causes an
- ; exception interrupt if the value is outside.
- ;
- ; The return address will be to the same instruction,
- ; which would normally loop endlessly. But since the
- ; interrupt is *conditional*, we can avoid it by making
- ; sure either the value we are testing or the bounds
- ; are changed after return.
- ;
- ; The trick is to put the bounds on the stack, and then
- ; - immediately before executing BOUND - restore SP so that
- ; they will be overwritten in a semi-predictable way.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- org 0100h
- ;;; Copy INT 21 vector to INT 05 (BOUND)
- ;;; !! this assumes GS=0000 as it is immediately after reset
- ;;; on actual machine, could have been modified by BIOS, EMM386 etc.
- and ax, 2020h
- and ax, 4040h
- xor al, 60h
- push ax
- pop si ; SI=0060
- xor al, 60h ; clear AX
- push ax ; save it
- dec ax
- sub al, 20h
- push ax
- pop di ; DI=-0021
- pop ax ; restore zero in AX
- and [gs:di+35h], ax ; clear [0014]
- and [gs:di+37h], ax ; clear [0016]
- push ax
- xor ax, [gs:si+24h] ; load [0084]
- xor [gs:di+35h], ax ; store [0014]
- pop ax
- push ax
- xor ax, [gs:si+26h] ; load [0086]
- xor [gs:di+37h], ax ; store [0016]
- pop ax
- ;;; Now set up bounds record on stack, which will get overwritten
- ;;; by flags/CS/IP on interrupt. Min/max is set to zero, so any
- ;;; positive number causes INT 05. On return, minimum bound is
- ;;; saved IP and maximum=saved CS, so this must be near the start
- ;;; of the code segment.
- ;;; In an EXE file, we could guarantee IP <= CS by placing
- ;;; the code below 0060; CS can never be that low because
- ;;; of the interrupt table and BIOS data area. But DOS should
- ;;; normally take up enough space in low memory that this isn't
- ;;; really necessary.
- push sp
- pop si ; save stack pointer in SI
- push ax ; reserve space for flags (don't care)
- push ax ; upper bound, overwritten with CS
- push ax ; lower bound, overwritten with IP
- push sp
- pop di ; DI=>bounds
- push si ; will be popped into SP just before BOUND
- ;;; Load SI with known IP of bound instruction
- ;;; set up other regs for printing string
- xor ax, 216bh
- xor ax, 2020h
- push ax
- pop si ; SI=014B
- xor ax, 2820h
- xor ax, 2020h ; AH=09
- push si
- pop dx
- inc dx
- inc dx
- inc dx ; DX=014E
- ;;; Restore stack pointer and execute BOUND
- ;;; !! race condition if hardware int occurs immediately after pop
- ;;; to be really sure DOS did its thing, we would have to check
- ;;; for a known return value from the function we are calling...
- pop sp
- bound si, [di]
- ;;; Proof of concept done, now cheating is allowed :)
- ret
- db "Hello world!",13,10,36
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement