cpu 8086 org 0x0000 stacksize: equ 0x20 db 0x55, 0xAA db 0x00 jmp init nop times (0x18 - ($-$$)) db 0 dw 0 dw pnp pnp: db "$PnP" db 1 ; version 1 db 2 ; 2 * 16 length dw 0 ; offset of next header db 0 db 0 ; checksum (filled by fix-rom) dd 0 ; device identifier dw 0 ; manufacturer string dw name ; product name string db 0,0,0 ; device type string db 0x20 ; device indicator, bit for "read cacheable" set dw 0 ; boot connection vector dw 0 ; boot disconnect vector dw 0 ; bootstrap entry point dw 0 ; reserved dw 0 name: db "rdos debug" init: push ds push es push si push di push ax push cx xor ax, ax mov si, ax mov di, ax ; load DS for mov ds, ax mov al, [cs:2] inc ax shr ax, 1 ; move down int 0x12 ptr to make space for us sub [0x413], ax ; calculate segment from kilobytes mov ax, [0x413] mov cl, 6 shl ax, cl ; load ES for relocate mov es, ax ; store interrupt vector mov word [3*4], int3entry mov word [3*4+2], es ; load DS for relocate push cs pop ds ; calculate our length mov cx, codeend rep movsb pop cx pop ax pop di pop si pop es pop ds retf crlf: xor bx, bx mov ax, 0x0e0a int 0x10 mov al, 0x0d int 0x10 ret space: xor bx, bx mov ax, 0x0e20 int 0x10 ret print16: ; setup bx and ah for int 10h call xor bx, bx mov ah, 0x0e mov cl, 4 ; this double-call is essentially a 4 times repeating loop call .c1 .c1: call .c2 .c2: ; grab highest nibble from dx mov al, dh ; remove highest nibble from dx shl dx, cl ; shift away second-highest nibble that we accidentally copied shr al, cl ; map 0-9 to ascii codes for '0' to '9' add al, 0x30 ; if result is larger than '9', ... cmp al, 0x3a jl .noadj ; ... add 7 so we continue at 'A' add al, 7 .noadj: int 0x10 ret printregs: mov cx, 13 xor bx, bx mov ah, 0x0e mov si, reg_ax .loop: push cx mov dx, [si+(names-reg_ax)] mov al, dl int 0x10 mov al, dh int 0x10 mov al, '=' int 0x10 lodsw mov dx, ax call print16 call space pop cx loop .loop mov dx, [reg_fl] mov si, fnames mov cx, 16 .floop: lodsb cmp al, '+' je .fskip test dx, 0x8000 jnz .fprnt mov al, '-' .fprnt: int 0x10 .fskip: shl dx, 1 loop .floop call space call crlf ret int3entry: ; save DS and AX mov [cs:reg_ds], ds mov [cs:reg_ax], ax ; use AX to load DS=CS mov ax, cs mov ds, ax ; pop IP, CS and flags from stack pop ax mov [reg_ip], ax pop ax mov [reg_cs], ax pop ax mov [reg_fl], ax ; save the other registers mov [reg_cx], cx mov [reg_dx], dx mov [reg_bx], bx mov [reg_sp], sp mov [reg_bp], bp mov [reg_si], si mov [reg_di], di ; save other segment registers we can access mov [reg_ss], ss mov [reg_es], es ; initialize other segments and setup stack mov es, ax mov ss, ax mov sp, (stack+stacksize) call crlf call printregs return: ; restore stack pointer mov ss, [reg_ss] mov sp, [reg_sp] ; push flags, CS and IP mov ax, [reg_fl] push ax mov ax, [reg_cs] push ax mov ax, [reg_ip] push ax ; restore GPR mov ax, [reg_ax] mov cx, [reg_cx] mov dx, [reg_dx] mov bx, [reg_bx] mov bp, [reg_bp] mov si, [reg_si] mov di, [reg_di] ; restore segment registers mov es, [reg_es] mov ds, [reg_ds] ; final jump back iret names: db "AXCXDXBXSPBPSIDI" db "DSESSSCSIPFL" fnames: db "++++ODIT" db "SZ+A+P+C" codeend: reg_ax: dw 0 reg_cx: dw 0 reg_dx: dw 0 reg_bx: dw 0 reg_sp: dw 0 reg_bp: dw 0 reg_si: dw 0 reg_di: dw 0 reg_es: dw 0 reg_cs: dw 0 reg_ss: dw 0 reg_ds: dw 0 reg_ip: dw 0 reg_fl: dw 0 stack: times stacksize dw 0 align 512