I am writing a bootloader with nasm. At the moment it is designed to output a welcome string, then record keystrokes while displaying them, printing the stored keystrokes upon finding the enter key, and finally halting.
bits 16
org 0x7C00
start: jmp main
bgetkey: pusha
mov ax, 0
mov ah, 10h
int 16h
mov [.buf], ax
popa
mov ax, [.buf]
ret
.buf dw 0
prints: mov ah, 0x0e
mov al, [si]
cmp al, 0
jz print_end
mov bh, 0x00
mov bl, 0x07
int 0x10
inc si
jmp prints
print_end: ret
main: mov ax, 0x0000 ; set register a
mov ds, ax ;
mov bx, mem
add bx, word 1
mov word [mem], bx
mov si, welcome ; set and prints
call prints ;
type: mov si, qbuf ; set prints ptr
call bgetkey ; capture input
mov [qbuf], al ; set char to sz
call prints ; call print str
mov bx, [mem] ; put chr in mem
cmp bx, stop ; compare loader
je oom ; end and memory
mov byte [bx], al
add bx, byte 1
mov [mem], bx ;
cmp byte [qbuf], 0x0D ; cmpr enter key
jne type ; continue next
mov si, newline ; print newline
call prints ;
mov bx, mem
printmem: cmp byte [bx], 0x00 ; check for zero
je halt ; halt the cpu
mov cl, [bx]
mov byte [qbuf], cl ; buffer and cpy
mov si, qbuf ; pointer to si
call prints ; print the char
inc bx
jmp printmem ; jump beginning
oom: mov si, outomem ; no more memory
call prints ; print message
halt: mov si, halting ; cpu is halting
call prints ; print last msg
hlt ; halt the cpu
welcome db "bootloader", 0x0A, 0x0D, 0x00
newline db 0x0A, 0x00
outomem db "out of memory", 0x0A, 0x0D, 0x00
halting db "halting", 0x00
qbuf dw 0, 0
mem db 0
times 0200h - 2 - ($ - $$)db 0
stop dw 0xAA55
The program is not functioning as desired. It ceaselessly prints the same character after enter is pressed. How is this error corrected?
The immediate problem is that your
prints
destroysbx
(because it setsbl
andbh
) so yourprintmem
loop which requiresbx
to be preserved blows up.However, it also destroys
al
so your input loop won't be storing the correct value in memory to start with, either.Furthermore, while you want
mem
to be a pointer tomem + 2
, it is actually a pointer tomem + 1
so you overwrite the pointer with the input. Also, you start printing frommem
and notmem + 2
.Finally, your input is not terminated by a zero that you are checking for, it's terminated by a
0x0D
(the enter).A working version could be:
PS: Learn to use a debugger.