x86 MASM 程序集 - 尽管有 FlushConsoleInputBuffer,输入缓冲区仍保留旧输入
x86 MASM Assembly - Input Buffer holds old input despite FlushConsoleInputBuffer
为了在 MASM 中练习汇编,我创建了一个应该执行以下操作的小程序:
- 打印"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.
我怀疑这是因为 ReadConsole
正在读取较旧的输入并因此提前终止函数,但 FlushConsoleInputBuffer
不应该清除旧输入吗?
ReadConsole
从控制台输入缓冲区读取 所有 个可用字符,并将它们存储在不受 FlushConsoleInputBuffer
影响的单独缓冲区中。您无法直接访问该缓冲区,也无法获取有关它的信息。因此,您必须使用 ReadConsole
阅读它直到行尾。默认情况下,行尾标有两个字节 CR (0x0D) 和 LF (0x0A)。因为你只读了一个字节,所以缓冲区中至少还剩下 LF。
用 ReadConsole
循环替换 FlushConsoleInputBuffer
以清空缓冲区,直到读取 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
为了在 MASM 中练习汇编,我创建了一个应该执行以下操作的小程序:
- 打印"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.
我怀疑这是因为 ReadConsole
正在读取较旧的输入并因此提前终止函数,但 FlushConsoleInputBuffer
不应该清除旧输入吗?
ReadConsole
从控制台输入缓冲区读取 所有 个可用字符,并将它们存储在不受 FlushConsoleInputBuffer
影响的单独缓冲区中。您无法直接访问该缓冲区,也无法获取有关它的信息。因此,您必须使用 ReadConsole
阅读它直到行尾。默认情况下,行尾标有两个字节 CR (0x0D) 和 LF (0x0A)。因为你只读了一个字节,所以缓冲区中至少还剩下 LF。
用 ReadConsole
循环替换 FlushConsoleInputBuffer
以清空缓冲区,直到读取 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