debug: Implement number parsing and editing of registers

This commit is contained in:
Nero 2020-05-18 22:35:41 +02:00
parent a386416f28
commit 8407275ba9
4 changed files with 246 additions and 104 deletions

136
debug/chario.asm Normal file
View File

@ -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

23
debug/edit.asm Normal file
View File

@ -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

View File

@ -2,16 +2,20 @@
; CS:DI error message ; CS:DI error message
parse_error: parse_error:
push si push si
mov si, .str1
call putcs
mov si, di mov si, di
call putcs call putcs
mov al, ':' mov si, .str2
call putc call putcs
mov al, ' '
call putc
pop si pop si
call putds call putds
jmp crlf jmp crlf
.str1: db "Not a ", 0
.str2: db ": ", 0
; Advance over whitespace
; IN DS:SI
eat_whitespace: eat_whitespace:
; peek on next char ; peek on next char
mov al, [si] mov al, [si]
@ -31,8 +35,9 @@ eat_whitespace:
.chars: db 0x09, 0x0A, 0x0D, 0x20 .chars: db 0x09, 0x0A, 0x0D, 0x20
.ret: ret .ret: ret
; IN: DS:SI string to read ; Parse a register name
; OUT: CF set if no match ; IN DS:SI string to read
; OUT CF set if no match
; BX register number * 2 if CF clear ; BX register number * 2 if CF clear
eat_register: eat_register:
push si push si
@ -55,4 +60,66 @@ eat_register:
.fail: pop si .fail: pop si
stc stc
ret 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

View File

@ -58,99 +58,8 @@ init: push ds
retf retf
%include "debug/parse.asm" %include "debug/parse.asm"
%include "debug/chario.asm"
; Print AL %include "debug/edit.asm"
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
int3entry: int3entry:
; save DS and load bss segment from IVT ; save DS and load bss segment from IVT
@ -191,7 +100,10 @@ loop: ; show prompt
mov al, '-' mov al, '-'
call putc call putc
; read data ; read data
call read mov byte [inmin], 1
mov byte [inmax], 16
mov word [ingetc], getc
call gets
pushf pushf
call crlf call crlf
popf popf
@ -228,7 +140,7 @@ return: ; restore stack pointer
%include "debug/names.asm" %include "debug/names.asm"
; Expects DI to mark end of command ; Expects DI to mark end of command
runcmd: mov si, cmdbuf runcmd: mov si, inbuf
lodsb lodsb
cmp al, 'g' cmp al, 'g'
je cmd_g je cmd_g
@ -256,6 +168,8 @@ cmd_r: cmp byte [si], 0
je printregs je printregs
call eat_register call eat_register
jc .err jc .err
call edit_word
call crlf
ret ret
.err: mov di, eat_register.emsg .err: mov di, eat_register.emsg
jmp parse_error jmp parse_error
@ -324,8 +238,10 @@ reg_ds: resw 1
reg_ip: resw 1 reg_ip: resw 1
reg_fl: resw 1 reg_fl: resw 1
cmdlen: equ 16 ingetc: resw 1
cmdbuf: resb cmdlen inmin: resb 1
inmax: resb 1
inbuf: resb 0x20
; reserve at least 80h words for stack ; reserve at least 80h words for stack
resw 0x80 resw 0x80