该代码应该将输入的字符串与各种硬编码选项进行比较以提供菜单。
这是我使用
的代码.stack 4096
...
GetStdHandle proto :dword
ReadConsoleA proto :dword, :dword, :dword, :dword, :dword
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
STD_INPUT_HANDLE equ -10
...
.data
...
bufSize = 80
inputHandle DWORD ?
buffer db bufSize dup(?)
choice DWORD ?
letterC DWORD "C"
...
.code
...
invoke GetStdHandle, STD_INPUT_HANDLE
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr choice,0
mov ESI, choice
mov EDI, letterC
CLD
MOV ECX,10
REPE CMPSB
...
它总是在最后一行REPE CMPSB
给我一个错误:
Application.exe中的0x00F6195F抛出异常:0xC0000005:访问冲突读取位置0x00000043。
答案 0 :(得分:3)
问题是您将源寄存器和目标寄存器都设置为错误的值 我会解释一下:
函数ReadConsole
具有以下签名:
BOOL WINAPI ReadConsole(
_In_ HANDLE hConsoleInput,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfCharsToRead,
_Out_ LPDWORD lpNumberOfCharsRead,
_In_opt_ LPVOID pInputControl
);
使用
mov ESI, choice
您正在将ReadConsole
,choice
的第四个参数复制到ESI
。
choice
包含NumberOfCharsRead
,因此它不是内存指针,而是长度值。这不起作用。
用
mov EDI, letterC
您将letterC
的值移至EDI
而不是其地址。要将地址设为EDI
,您必须使用
mov EDI, OFFSET letterC
此错误在您的错误消息中显而易见,其中包含
访问冲突读取位置0x00000043。
0x00000043
的值等于字符C
的0x char值,0x43。要获取其地址 - 这是正确的 - 您可以使用LEA
指令,如lea EDI, letterC
或OFFSET
指令,它更有效。读取或写入值作为地址几乎总是会导致错误。
为了使其正确,请考虑以下方法:
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr choice,0
CLD
MOV ESI, OFFSET buffer ; address of buffer is source
MOV EDI, OFFSET letterC ; address of letterC is destination
MOV ECX, choice ; length of string is choice (bytes read)
REPE CMPSB ; execute
此解决方案更好,但它包含一个主要错误:REPE CMPSB
比较字符并继续比较它们,只要它们相等。但是你的letterC
只有一个字符长,所以你在传递C
字符后会出现溢出 - 第二次迭代。
你的问题不清楚你真正的期望,所以以下只是猜测:
可能的替代方法是使用REPNE SCASB
letterC
AL
中的MOV AL, letterC
来搜索C
的第一个匹配项:
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr choice,0
CLD
MOV EDI, OFFSET buffer ; address of buffer is search source
MOV EAX, letterC ; value of letterC
MOV ECX, choice ; length of string is choice (bytes read)
REPNE SCASB ; execute