【问题标题】:x86 MASM Assembly - Input Buffer holds old input despite FlushConsoleInputBufferx86 MASM 程序集 - 尽管 FlushConsoleInputBuffer 输入缓冲区保留旧输入
【发布时间】:2018-12-08 16:00:13
【问题描述】:

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

  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。

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

【问题讨论】:

    标签: windows winapi assembly x86 masm32


    【解决方案1】:

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

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

    .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
    

    【讨论】:

    • 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    相关资源
    最近更新 更多