在汇编语言中比较字符串时出错: 0xC0000005:访问冲突读取位置0x00000043



代码应该将输入的字符串与各种硬编码选项进行比较以提供菜单。

这是我正在使用的代码

.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

在应用程序.exe中0x00F6195F引发异常: 0xC0000005:访问冲突读取位置0x00000043。

问题是您将源寄存器和目标寄存器都设置为错误的值。
我将解释一下:

函数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的 ASCII 字符值,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与字符letterCAL(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

最新更新