x86 MASM 程序集 - 尽管 FlushConsoleInputBuffer 输入缓冲区仍保留旧输入 [英] x86 MASM Assembly - Input Buffer holds old input despite FlushConsoleInputBuffer
问题描述
为了在 MASM 中练习汇编,我创建了一个应该执行以下操作的小程序:
To practice assembly in MASM, I created a small program that is supposed to do the do the following:
- 在屏幕上打印Type a:"
- 从输入缓冲区读取一个字符,然后刷新
- 如果字符是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屋!