I am writing a bootloader, and it's functionality is basically limited to printing a string, then copying keyboard characters to the screen as they are typed. While writing the routines that read and write the key, I noticed my print routine was not detecting the null terminator in offset (plus) one of a double word array that stores the typed key. Right now I'm simply resetting the terminator, but I thought I'd ask what is happening here. The line in question is marked with ; THIS LINE
.
bits 16
org 0x7C00
start: jmp main
; IMPORTED GET KEY BLOCKING
; IN: NONE
; OUT: AX
bgetkey:
pusha
mov ax, 0
mov ah, 10h
int 16h
mov [.buf], ax
popa
mov ax, [.buf]
ret
.buf dw 0
; END IMPORTED FILE
; IMPORTED PRINT STRING TO SCREEN
; IN: ds->si
; OUT: NONE
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
; END IMPORTED FILE
main:
mov ax, 0x0000 ; clear ax and
mov ds, ax ; data segment
mov si, welcome
call prints
type:
mov si, qbuf
call bgetkey
mov [qbuf], ax
mov dword [qbuf + 1], 0 ; THIS LINE
call prints
jmp type
welcome db "moose os", 0x0A, 0x0D, 0x00
newline db 0x0D, 0x0A, 0x00
qbuf dw 0, 0
times 0200h - 2 - ($ - $$) db 0
dw 0xAA55
This is the output of typing "abcdefg" if I comment out the line in question:
This is the desired output with line uncommented:
Why must I reset qbuf + 1
?
The problem is that INT 16h AH=00h returns a ASCII character code in AL and an scan code in AH. The
mov [qbuf], ax
instruction stores both in the buffer, but INT 10h AH=0Eh only prints ASCII characters. It ends up interpreting the scan code you stored in the buffer as an ASCII character and displays it on screen accordingly.Your
mov dword [qbuf + 1], 0
statement fixes this problem by writing 4 zero bytes after the first character inqbuf
. This overwrites the scan code stored in the second byte ofqbuf
. It also sets the remaining two bytes to 0 along with one more byte beyond the end of the 4 byte longqbuf
. Anything afterqbuf
would be overwritten by this statement, but fortunately there's nothing there.What you should be doing this:
The second MOV instruction isn't necessary in your program as it is now, the byte will already be 0. It's still a good idea though so your code doesn't break if you end up using the
qbuf
for something else earlier in your program.