diff --git a/boot/monitor.asm b/boot/monitor.asm new file mode 100644 index 0000000..76fc4e9 --- /dev/null +++ b/boot/monitor.asm @@ -0,0 +1,261 @@ +; monitor program that fits in a boot sector +; for debugging disk i/o and bootstrapping + +%define base (0x10000 - 0x400) + + org base + + ; relocate to end of memory +init: ; set up src addr + xor ax, ax + mov ds, ax + mov si, 0x7C00 + ; calculate target segment + mov ax, [0x413] + mov cl, 6 + shl ax, cl + sub ax, 0x1000 + ; set up dst addr + mov es, ax + mov di, base + ; set up stack + mov ss, ax + mov sp, di + ; relocate + mov cx, 0x100 + rep movsw + ; set up intr vectors + mov bx, 1*4 + call .l02 + ; enter + mov si, 0x7C00-1 + mov byte [si], 0xCC + push cs + push si + retf + + ; call here = run proc tail twice +.l02: call .l01 +.l01: mov word [bx], entry + mov word [bx+2], es + add bx, 2*4 + ret + +nl: mov al, 0x0A + call putc + mov al, 0x0D + jmp putc + + ; print full register set +printr: call nl + xor si, si +.l01: call .l02 + add si, 2 + cmp si, 18 + jc .l01 + mov si, 22 + call .l02 + les bx, [ss:bp+18] + jmp dump + +.l02: mov ah, 0x0e + mov al, [cs:lbls+si] + int 0x10 + mov al, [cs:lbls+si+1] + int 0x10 + mov al, '=' + int 0x10 + mov dx, [ss:bp+si] + call printd +space: mov al, ' ' +putc: mov ah, 0x0e + int 0x10 + ret + + ; print far ptr ES:BX +printf: mov dx, es + call printd + mov al, ':' + call putc + mov dx, bx + call printd + jmp space + + ; print 16 bytes from ES:BX +dump: call printf + push bx + mov cx, 0x10 +.l01: mov dh, [es:bx] + inc bx + push cx + call printb + call space + pop cx + loop .l01 + pop bx + ret + +printd: call printb ; print dx +printb: call .l01 ; print dh +.l01: mov cl, 4 + ; 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 +printn: ; 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: mov ah, 0x0e + int 0x10 + ret + +getc: xor ax, ax + int 0x16 + test al, al + jz getc + test al, 0x80 + jnz getc + cmp al, 0x60 + jc .ret + sub al, 0x20 +.ret: ret + + ; reads CX hex digits into DX + ; DX needs to be zero on entry +input: call getc + cmp al, 0x20 + je .err + ; must be above '0' + sub al, 0x30 + jc input + ; if >9, turn 'A' to A + cmp al, 0x0A + jc .noadj + sub al, 7 +.noadj: ; must be smaller than 'F' + cmp al, 0x10 + jnc input + ; append to DX + push cx + mov cl, 4 + shl dx, cl + or dl, al + pop cx + ; print, loop & clear exit + call printn + loop input + call space + clc + ret +.err: call space + stc + ret + + ; edit word at ES:BX + ; space exits with carry +editw: mov dx, [es:bx] + call printd + mov al, '.' + call putc + mov cx, 4 + call input + jc .err + mov [es:bx], dx +.err: ret + +entry: push es + push ds + push di + push si + push bp + push bx + push dx + push cx + push ax + mov bp, sp + +cmd_r: call printr + ; reset segment register +cmd: mov ax, cs + mov ds, ax + mov es, ax + ; display prompt + call nl + mov al, '-' + call putc +.l01: call getc + cmp al, 0x41 + jc .l01 + ; process input char + call putc + push ax + call space + pop ax + ; branch out into commands + les bx, [defptr] + cmp al, 'D' + je cmd_d + cmp al, 'G' + je exit + cmp al, 'R' + je cmd_r + ; set working ptr + cmp al, 'S' + je cmd_s + cmp al, 'O' + je cmd_o + +err: mov al, '?' + call putc + jmp cmd + +cmd_d: mov cx, 8 +.l01: push cx + call nl + call dump + pop cx + add bx, 0x10 + mov [defptr], bx + loop .l01 + jmp cmd + +cmd_o: mov bx, defptr + jmp cmd_s.l01 + +cmd_s: mov bx, defptr+2 +.l01: call editw + jmp cmd + +hlt: hlt + jmp hlt + +exit: pop ax + pop cx + pop dx + pop bx + pop bp + pop si + pop di + pop ds + pop es + iret + + ; names for registers +lbls: db "AXCXDXBXBPSIDI" ; gpr + db "DSES" ; seg regs + db "IPCSFL" ; iret frmae + +defptr: dw 0x7C00, 0 + + times 510-($-$$) db 0x00 + db 0x55,0xaa + +section .bss + +line: resb 0x100