diff --git a/debug/chario.asm b/debug/chario.asm new file mode 100644 index 0000000..ba2269a --- /dev/null +++ b/debug/chario.asm @@ -0,0 +1,136 @@ + ; Print AL +space: mov al, ' ' +putc: xor bx, bx + mov ah, 0x0e + int 0x10 + ret + + ; Print code string CS:SI +putcs: push ds + push cs + pop ds + call putds + pop ds + ret + + ; Print data string DS:SI +putds: lodsb + test al, al + jz .ret + call putc + jmp putds +.ret: ret + +crlf: mov al, 0x0A + call putc + mov al, 0x0D + jmp putc + +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 + + ; Read character +getc: xor ax, ax + int 0x16 + test al, al + jz getc + test al, 0x80 + jnz getc + ret + + ; Read uppercased character +getcu: call getc + cmp al, 'a' + jc .ret + cmp al, 'z' + ja .ret + and al, 0xDF +.ret: ret + + ; Read hexadecimal character +getch: call getcu + ; everything above F is invalid + cmp al, 'F' + ja getch + ; everything above or equal A is ok + cmp al, 'A' + jae .ret + ; everything above 9 is invalid + cmp al, '9' + ja getc + ; everything above or equal 0 is valid + cmp al, '0' + jae .ret + ; everything above or equal ' ' is invalid + cmp al, ' ' + jae getch +.ret: ret + + ; Read string into inbuf + ; IN ingetc ptr to getc function + ; inlen max number of chars +gets: mov di, inbuf + ; calculate max pointer for writing + mov dx, [inmin] +.loop: call [ingetc] + ; test for Ctrl+C, Enter and Backspace + cmp al, 0x03 + je .can + cmp al, 0x0D + je .enter + cmp al, 0x08 + je .bs + ; ignore other ctl chars + cmp al, 0x20 + jc .loop + ; check if we are full + mov bx, di + sub bx, inbuf + ; bl is now number of characters we have + cmp bl, dh + jnc .loop + stosb + call putc + jmp .loop + ; backspace: print, print space, print backspace again +.bs: cmp di, inbuf + jbe .loop + push ax + call putc + call space + pop ax + call putc + dec di + jmp .loop + ; ctrl+c: return with carry set +.can: stc + ret + ; enter: if enough chars, return +.enter: mov bx, di + sub bx, inbuf + cmp bl, dl + jc .loop + xor al, al + stosb + ret diff --git a/debug/edit.asm b/debug/edit.asm new file mode 100644 index 0000000..93fe8cf --- /dev/null +++ b/debug/edit.asm @@ -0,0 +1,23 @@ + ; let the user edit the word at ES:BX +edit_word: + push bx + mov dx, [es:bx] + call print16 + mov al, '.' + call putc + mov byte [inmin], 4 + mov byte [inmax], 4 + mov word [ingetc], getch + call gets + pop bx + jc .ret + + mov si, inbuf + call eat_hex_word + jc .err + mov [es:bx], dx + +.ret: ret +.err: call crlf + mov di, eat_hex_word.emsg + jmp parse_error diff --git a/debug/parse.asm b/debug/parse.asm index a99f9e4..9a3e48a 100644 --- a/debug/parse.asm +++ b/debug/parse.asm @@ -2,16 +2,20 @@ ; CS:DI error message parse_error: push si + mov si, .str1 + call putcs mov si, di call putcs - mov al, ':' - call putc - mov al, ' ' - call putc + mov si, .str2 + call putcs pop si call putds jmp crlf +.str1: db "Not a ", 0 +.str2: db ": ", 0 + ; Advance over whitespace + ; IN DS:SI eat_whitespace: ; peek on next char mov al, [si] @@ -31,8 +35,9 @@ eat_whitespace: .chars: db 0x09, 0x0A, 0x0D, 0x20 .ret: ret - ; IN: DS:SI string to read - ; OUT: CF set if no match + ; Parse a register name + ; IN DS:SI string to read + ; OUT CF set if no match ; BX register number * 2 if CF clear eat_register: push si @@ -55,4 +60,66 @@ eat_register: .fail: pop si stc ret -.emsg: db "Not a register name", 0 +.emsg: db "register name", 0 + + ; Parse hex digit + ; IN DS:SI + ; OUT AL +eat_hex_digit: + push si + lodsb + sub al, '0' + jc .err + cmp al, 9 + jna .ret + sub al, 7 + cmp al, 0xF + ja .err +.ret: add sp, 2 + ret +.err: pop si + stc + ret +.emsg: db "hex digit", 0 + + ; Parse hexadecimal byte + ; IN DS:SI + ; OUT DL or carry set +eat_hex_byte: + push si + mov cl, 4 + xor dl, dl + + call eat_hex_digit + jc .err + or dl, al + shl dl, cl + call eat_hex_digit + jc .err + or dl, al + + add sp, 2 + ret +.err: pop si + stc + ret +.emsg: db "hex byte", 0 + + ; Parse hexadecimal word + ; OUT DX or carry set +eat_hex_word: + push si + xor dx, dx + + call eat_hex_byte + jc .err + mov dh, dl + call eat_hex_byte + jc .err + + add sp, 2 + ret +.err: pop si + stc + ret +.emsg: db "hex word", 0 diff --git a/rom/debug.asm b/rom/debug.asm index 70420ea..101efd2 100644 --- a/rom/debug.asm +++ b/rom/debug.asm @@ -58,99 +58,8 @@ init: push ds retf %include "debug/parse.asm" - - ; Print AL -space: mov al, ' ' -putc: xor bx, bx - mov ah, 0x0e - int 0x10 - ret - - ; Print code string CS:SI -putcs: push ds - push cs - pop ds - call putds - pop ds - ret - - ; Print data string DS:SI -putds: lodsb - test al, al - jz .ret - call putc - jmp putds -.ret: ret - -crlf: mov al, 0x0A - call putc - mov al, 0x0D - jmp putc - -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 - -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-1 - 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: xor al, al - stosb - stc - ret -.enter: xor al, al - stosb - ret + %include "debug/chario.asm" + %include "debug/edit.asm" int3entry: ; save DS and load bss segment from IVT @@ -191,7 +100,10 @@ loop: ; show prompt mov al, '-' call putc ; read data - call read + mov byte [inmin], 1 + mov byte [inmax], 16 + mov word [ingetc], getc + call gets pushf call crlf popf @@ -228,7 +140,7 @@ return: ; restore stack pointer %include "debug/names.asm" ; Expects DI to mark end of command -runcmd: mov si, cmdbuf +runcmd: mov si, inbuf lodsb cmp al, 'g' je cmd_g @@ -256,6 +168,8 @@ cmd_r: cmp byte [si], 0 je printregs call eat_register jc .err + call edit_word + call crlf ret .err: mov di, eat_register.emsg jmp parse_error @@ -324,8 +238,10 @@ reg_ds: resw 1 reg_ip: resw 1 reg_fl: resw 1 -cmdlen: equ 16 -cmdbuf: resb cmdlen +ingetc: resw 1 +inmin: resb 1 +inmax: resb 1 +inbuf: resb 0x20 ; reserve at least 80h words for stack resw 0x80