x86 MASM 程序集 - 尽管 FlushConsoleInputBuffer 输入缓冲区仍保留旧输入 [英] x86 MASM Assembly - Input Buffer holds old input despite FlushConsoleInputBuffer

查看:25
本文介绍了x86 MASM 程序集 - 尽管 FlushConsoleInputBuffer 输入缓冲区仍保留旧输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了在 MASM 中练习汇编,我创建了一个应该执行以下操作的小程序:

To practice assembly in MASM, I created a small program that is supposed to do the do the following:

  1. 在屏幕上打印Type a:"
  2. 从输入缓冲区读取一个字符,然后刷新
  3. 如果字符是a",则跳出循环结束程序,否则从第一步开始重复

我的代码如下:

.386


.model flat,stdcall


include \masm32\include\kernel32.inc ; Defines Symbols To Be Used for the kernel32 library


includelib \masm32\lib\kernel32.lib



STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10

.code



entryPt proc
    local inHandle:DWORD
    local outHandle:DWORD
    local noOfCharsWritten:DWORD
    ; Get Standard Output Handle
    push STD_OUTPUT_HANDLE
    call GetStdHandle
    mov outHandle,eax

    ; Get Standard Input Handle
    push STD_INPUT_HANDLE
    call GetStdHandle
    mov inHandle,eax

    .while (eax == eax) ; while (true)

        ; Print "Type a: "
        push 0
        lea eax,noOfCharsWritten
        push eax
        push sizeof txt
        push offset txt
        push outHandle
        call WriteConsoleA

        ; Poll for a byte
        call getChar

        .if (al == "a") ; if the byte was "a"...
            .break ; ...then end the loop
        .endif

    .endw

    ; Leave with exit code 0
    push 0
    call ExitProcess
entryPt endp

getChar proc
    local inHandle:DWORD
    local noOfCharsRead:DWORD
    local resBt:BYTE
    ; Get the Standard Input Handle
    push STD_INPUT_HANDLE
    call GetStdHandle
    mov inHandle,eax
    ; Read one char from the console, put the result in resBt and the number of chars read in noOfCharsRead
    push 0
    lea eax,noOfCharsRead
    push eax
    push 1
    lea eax,resBt
    push eax
    push inHandle
    call ReadConsoleA

    ; Flush Console Input Buffer
    push inHandle
    call FlushConsoleInputBuffer

    ; Return the result in the accumulator
    movzx eax,resBt
    ret
getChar endp
.data

txt db "Type a: "

end entryPt

当输入a"时,程序会退出,就像它应该的那样.但是,如果我输入任何不是a"的东西(例如,s"),而不是再次询问Type a:",只一次,它会写Type a: Type a: Type a:"之前查询另一个字节.写一个以上的非 a 字符会导致更多的Type a:"s.

When typing "a", the program will exit, just like it should. However, should I type anything that is not "a" (for example, "s"), instead of inquiring "Type a: " again, only once, it will instead write "Type a: Type a: Type a:" before inquiring for another byte. Writing more than one non-a character will result in even more "Type a: "s.

我怀疑这是因为 ReadConsole 正在读取旧输入并因此提前终止函数,但是 FlushConsoleInputBuffer 不应该清除旧输入吗?

I suspect this is because ReadConsole is reading the older input and therefore terminating the function early, but shouldn't FlushConsoleInputBuffer have cleaned out the old input?

推荐答案

ReadConsole 从控制台输入缓冲区读取所有 可用字符并将它们存储在一个单独的缓冲区中不受 FlushConsoleInputBuffer 的影响.您无法直接访问该缓冲区,也无法获取有关它的信息.因此,您必须使用 ReadConsole 阅读它,直到该行结束.默认情况下,行尾用两个字节 CR (0x0D) 和 LF (0x0A) 标记.由于您只读取了一个字节,因此缓冲区中至少还剩下 LF.

ReadConsole reads all available characters from the console input buffer and stores them in a separate buffer that is not affected by FlushConsoleInputBuffer. You haven't a direct access to that buffer and can't get information about it. So, you have to read it with ReadConsole until the end of the line. By default, the end of the line is marked with the two bytes CR (0x0D) and LF (0x0A). Since you read just one byte, there is left at least the LF in the buffer.

FlushConsoleInputBuffer 替换为 ReadConsole 循环以清空缓冲区,直到读取 LF:

Replace the FlushConsoleInputBuffer with a ReadConsole loop to empty the buffer until LF is read:

.model flat,stdcall

include \masm32\include\kernel32.inc ; Defines Symbols To Be Used for the kernel32 library
includelib \masm32\lib\kernel32.lib

STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10

.code

entryPt proc
    local inHandle:DWORD
    local outHandle:DWORD
    local noOfCharsWritten:DWORD
    ; Get Standard Output Handle
    push STD_OUTPUT_HANDLE
    call GetStdHandle
    mov outHandle,eax

    ; Get Standard Input Handle
    push STD_INPUT_HANDLE
    call GetStdHandle
    mov inHandle,eax

    .while (eax == eax) ; while (true)

        ; Print "Type a: "
        push 0
        lea eax,noOfCharsWritten
        push eax
        push sizeof txt
        push offset txt
        push outHandle
        call WriteConsoleA

        ; Poll for a byte
        call getChar

        .if (al == "a") ; if the byte was "a"...
            .break ; ...then end the loop
        .endif

    .endw

    ; Leave with exit code 0
    push 0
    call ExitProcess
entryPt endp

getChar proc
    local inHandle:DWORD
    local noOfCharsRead:DWORD
    local resBt:BYTE, dummy:BYTE

    ; Get the Standard Input Handle
    push STD_INPUT_HANDLE
    call GetStdHandle
    mov inHandle,eax

    ; Read one char from the console, put the result in resBt and the number of chars read in noOfCharsRead
    push 0
    lea eax,noOfCharsRead
    push eax
    push 1
    lea eax,resBt
    push eax
    push inHandle
    call ReadConsoleA

    ; Flush
    mov al, resBt
    mov dummy, al
    FlushLoop:
    cmp dummy, 0Ah
    je EndOfFlush
    invoke ReadConsoleA, inHandle, ADDR dummy, 1, ADDR noOfCharsRead, 0
    jmp FlushLoop
    EndOfFlush:

    ; Return the result in the accumulator

    movzx eax,resBt
    ret
getChar endp
.data

txt db "Type a: "

end entryPt

这篇关于x86 MASM 程序集 - 尽管 FlushConsoleInputBuffer 输入缓冲区仍保留旧输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆