我正在编写一个bootloader,它的功能基本上只限于打印一个字符串,然后在键入时将键盘字符复制到屏幕上。在编写读取和写入密钥的例程时,我注意到我的打印例程没有检测到偏移(加号)存储键入密钥的双字数组中的空终止符。现在我只是重置终结器,但我想我会问这里发生了什么。有问题的行标有Setup::createYAMLMetadataConfiguration
。
; THIS LINE
如果我注释掉有问题的行,这是输入“abcdefg”的输出:
这是取消注释行的所需输出:
为什么我必须重置 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
?
答案 0 :(得分:2)
问题是INT 16h AH = 00h返回AL中的ASCII字符代码和AH中的扫描代码。 mov [qbuf], ax
指令存储在缓冲区中,但INT 10h AH = 0Eh仅打印ASCII字符。它最终将您存储在缓冲区中的扫描代码解释为ASCII字符,并相应地在屏幕上显示。
您的mov dword [qbuf + 1], 0
语句通过在qbuf
中的第一个字符后写入4个零字节来解决此问题。这会覆盖存储在qbuf
的第二个字节中的扫描代码。它还将剩余的两个字节设置为0,并在4字节长qbuf
的末尾之外再设置一个字节。 qbuf
之后的任何内容都会被此声明覆盖,但幸运的是那里没有任何内容。
你应该做什么:
call bgetkey
mov [qbuf], al
mov byte [qbuf + 1], 0
call prints
现在你的程序中没有必要使用第二条MOV指令,字节已经是0.虽然如果最终使用qbuf
你的代码不会破坏,但仍然是个好主意。在你的程序中更早的其他内容。