cpu 8086 org 0x0000 ; interrupt vector we store addr of data segment in bssvec: equ 0xB6 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", 0 init: push ds push ax push cx ; DS := 0 xor ax, ax mov ds, ax ; allocate a single kilobyte from end of lowmem dec word [0x413] ; calculate segment from kilobytes mov ax, [0x413] mov cl, 6 shl ax, cl ; store ptr to our data segment in B6h vector mov word [bssvec*4], ax ; set entry points vectors mov word [1*4], int3entry mov word [1*4+2], cs mov word [3*4], int3entry mov word [3*4+2], cs pop cx pop ax 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, [cs:si+names] 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: mov al, [cs:si] inc si cmp al, '+' je .fskip test dx, 0x8000 jnz .fprnt mov al, '-' .fprnt: int 0x10 .fskip: shl dx, 1 loop .floop call space ret int3entry: ; save DS and AX push ds push ax ; DS=0 xor ax, ax mov ds, ax ; load bss segment mov ds, [bssvec*4] ; pop AX and DX pop ax mov [reg_ax], ax pop ax mov [reg_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 ax, ds mov es, ax mov ss, ax mov sp, stack call crlf call printregs mov dx, ds call print16 loop: ; new line & show prompt call crlf mov al, '-' int 0x10 ; read data call read jc loop ; execute call crlf mov al, [cmdbuf] call runcmd jmp loop runcmd: cmp al, 'r' je printregs cmp al, 'g' je go cmp al, 't' je step ; print a question mark xor bx, bx mov ax, 0x0e3F int 0x10 ret go: and word [reg_fl+1], 0xfe jmp return step: or word [reg_fl+1], 0x03 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 ; DS must be last mov es, [reg_es] mov ds, [reg_ds] ; final jump back iret names: ; general purpose regs db "AXCXDXBXSPBPSIDI" ; segment regs db "ESCSSSDS" ; special regs db "IPFL" fnames: ; control flags db "++++ODIT" ; status flags db "SZ+A+P+C" getc: xor ax, ax int 0x16 test al, al jz getc ret read: mov di, cmdbuf .loop: call getc cmp al, 0x03 je .can cmp al, 0x0D je .enter cmp al, 0x08 je .bs cmp di, cmdbuf+cmdlen jnc .loop stosb mov ah, 0x0e xor bx, bx int 0x10 jmp .loop ret .bs: cmp di, cmdbuf jbe .loop xor bx, bx mov ax, 0x0e08 int 0x10 mov al, 0x20 int 0x10 mov al, 0x08 int 0x10 dec di jmp .loop .can: stc .enter: ret align 512 absolute 0 reg_ax: resw 1 reg_cx: resw 1 reg_dx: resw 1 reg_bx: resw 1 reg_sp: resw 1 reg_bp: resw 1 reg_si: resw 1 reg_di: resw 1 reg_es: resw 1 reg_cs: resw 1 reg_ss: resw 1 reg_ds: resw 1 reg_ip: resw 1 reg_fl: resw 1 cmdlen: equ 16 cmdbuf: resb cmdlen ; reserve at least 80h words for stack resw 0x80 alignb 1024 stack: