这是溢出,还是更多的键盘数据?

Is this an overflow, or maybe more keyboard data?

我正在编写引导加载程序,它的功能基本上仅限于打印字符串,然后在键入时将键盘字符复制到屏幕上。在编写读取和写入密钥的例程时,我注意到我的打印例程没有检测到存储键入密钥的双字数组的偏移量(加号)中的空终止符。现在我只是在重置终结器,但我想我会问这里发生了什么。有问题的行标有 ; 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

如果我注释掉有问题的行,这就是键入 "abcdefg" 的输出:

这是未注释行的所需输出:

为什么我必须重置 qbuf + 1

问题是INT 16h AH=00h returns一个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 用于您程序中的其他内容。