Winapi 为什么如果我输入的数字变高,它会返回错误的数字
我有以下代码,但我不明白为什么如果我输入的数字太高,它会返回错误的数字。这可能是因为数据类型以及除法和乘法,但我不知道确切的原因。如果你知道为什么我会感谢你的帮助Winapi 为什么如果我输入的数字变高,它会返回错误的数字,winapi,assembly,x86,masm,Winapi,Assembly,X86,Masm,我有以下代码,但我不明白为什么如果我输入的数字太高,它会返回错误的数字。这可能是因为数据类型以及除法和乘法,但我不知道确切的原因。如果你知道为什么我会感谢你的帮助 .586 .model flat, stdcall option casemap :none .stack 4096 extrn ExitProcess@4: proc GetStdHandle proto :dword ReadConsoleA proto :dword, :dword, :dword, :dword, :dwo
.586
.model flat, stdcall
option casemap :none
.stack 4096
extrn ExitProcess@4: proc
GetStdHandle proto :dword
ReadConsoleA proto :dword, :dword, :dword, :dword, :dword
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11
.data
bufSize = 80
inputHandle DWORD ?
buffer db bufSize dup(?)
bytes_read DWORD ?
sum_string db "The number was ",0
outputHandle DWORD ?
bytes_written dd ?
actualNumber dw 0
asciiBuf db 4 dup (0)
.code
main:
invoke GetStdHandle, STD_INPUT_HANDLE
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr bytes_read,0
sub bytes_read, 2 ; -2 to remove cr,lf
mov ebx,0
mov al, byte ptr buffer+[ebx]
sub al,30h
add [actualNumber],ax
getNext:
inc bx
cmp ebx,bytes_read
jz cont
mov ax,10
mul [actualNumber]
mov actualNumber,ax
mov al, byte ptr buffer+[ebx]
sub al,30h
add actualNumber,ax
jmp getNext
cont:
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov outputHandle, eax
mov eax,LENGTHOF sum_string ;length of sum_string
invoke WriteConsoleA, outputHandle, addr sum_string, eax, addr bytes_written, 0
mov ax,[actualNumber]
mov cl,10
mov bl,3
nextNum:
xor edx, edx
div cl
add ah,30h
mov byte ptr asciiBuf+[ebx],ah
dec ebx
mov ah,0
cmp al,0
ja nextNum
mov eax,4
invoke WriteConsoleA, outputHandle, addr asciiBuf, eax, addr bytes_written, 0
mov eax,0
mov eax,bytes_written
push 0
call ExitProcess@4
end main
是的,您的返回值被一个最大值限制是合理的。此最大值为255的
字节
边界或65536的单词
边界。让我逐一解释原因:
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr bytes_read,0
sub bytes_read, 2 ; -2 to remove cr,lf
mov ebx,0
mov al, byte ptr buffer+[ebx]
sub al,30h
add [actualNumber],ax
在本部分中,您将调用Win32 API
函数,该函数始终返回寄存器EAX
中的return
值。返回后,将32位返回值中较低的8位分配给字节ptr buffer+[ebx]
,从中减去30h
。然后通过添加[actualNumber],AX
将刚刚在AL
中修改的8位和AH
中保留的返回值作为块AX
添加到WORD
变量。因此,AH
源于EAX
返回值,相当于未定义的。如果它是0
,您可能会很幸运,但这不应该被假设
下一个问题是以下子程序:
getNext:
inc bx
cmp ebx,bytes_read
jz cont
mov ax,10
mul [actualNumber]
mov actualNumber,ax
mov al, byte ptr buffer+[ebx]
sub al,30h
add actualNumber,ax
jmp getNext
您正在将十进制基数10
移动到WORD
寄存器AX
并将其乘以WORD
变量[actualNumber]
。到目前为止,一切顺利。但是16位*16位MUL
的结果返回到寄存器对AX:DX
(低:高)。因此,您的mov实际数ax
仅mov
s变量的低16位(DX
被忽略,将结果限制为result%65536
)。所以你的最大可能结果是MAX_WORD=65535。其他的一切只会给你AX中的模
在mov al之后,字节ptr buffer+[ebx]
用buffer[ebx]
指向的byte
覆盖此结果的下8位,然后从中减去30h
。记住:结果的高8位仍然保留在AH中,AX的高8位
然后使用add actualNumber,ax
将该值(重新)添加到变量actualNumber
。让我浓缩最后两段:
Operation | AX |
| AL AH |
mov actualNumber,ax | ................ |
mov al, byte ptr buffer+[ebx] | ........ AH |
sub al,30h | ....-30h AH |
add actualNumber,ax | ................ |
因此,您正在通过AL
修改AX
的低8位,然后将actualNumber
/AH
的高8位添加到自身中-有效地将AH
加倍,然后将其添加到actualNumber
,如下所示:
actualNumber = 256 * (2 * AH) + (byte ptr buffer[ebx]-30h) ; I doubt you want that ;-)
这些问题可能会导致与预期结果的几处偏差。是的,您的返回值被最大值限制是合理的。此最大值为255的字节
边界或65536的单词
边界。让我逐一解释原因:
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr bytes_read,0
sub bytes_read, 2 ; -2 to remove cr,lf
mov ebx,0
mov al, byte ptr buffer+[ebx]
sub al,30h
add [actualNumber],ax
在本部分中,您将调用Win32 API
函数,该函数始终返回寄存器EAX
中的return
值。返回后,将32位返回值中较低的8位分配给字节ptr buffer+[ebx]
,从中减去30h
。然后通过添加[actualNumber],AX
将刚刚在AL
中修改的8位和AH
中保留的返回值作为块AX
添加到WORD
变量。因此,AH
源于EAX
返回值,相当于未定义的。如果它是0
,您可能会很幸运,但这不应该被假设
下一个问题是以下子程序:
getNext:
inc bx
cmp ebx,bytes_read
jz cont
mov ax,10
mul [actualNumber]
mov actualNumber,ax
mov al, byte ptr buffer+[ebx]
sub al,30h
add actualNumber,ax
jmp getNext
您正在将十进制基数10
移动到WORD
寄存器AX
并将其乘以WORD
变量[actualNumber]
。到目前为止,一切顺利。但是16位*16位MUL
的结果返回到寄存器对AX:DX
(低:高)。因此,您的mov实际数ax
仅mov
s变量的低16位(DX
被忽略,将结果限制为result%65536
)。所以你的最大可能结果是MAX_WORD=65535。其他的一切只会给你AX中的模
在mov al之后,字节ptr buffer+[ebx]
用buffer[ebx]
指向的byte
覆盖此结果的下8位,然后从中减去30h
。记住:结果的高8位仍然保留在AH中,AX的高8位
然后使用add actualNumber,ax
将该值(重新)添加到变量actualNumber
。让我浓缩最后两段:
Operation | AX |
| AL AH |
mov actualNumber,ax | ................ |
mov al, byte ptr buffer+[ebx] | ........ AH |
sub al,30h | ....-30h AH |
add actualNumber,ax | ................ |
因此,您正在通过AL
修改AX
的低8位,然后将actualNumber
/AH
的高8位添加到自身中-有效地将AH
加倍,然后将其添加到actualNumber
,如下所示:
actualNumber = 256 * (2 * AH) + (byte ptr buffer[ebx]-30h) ; I doubt you want that ;-)
这些问题可能会导致与预期结果的一些偏差。Microsoft在其Visual Studio环境中有一个很好的调试器。也可以。当你说“太高”和“错误的数字”时,你并没有给我们提供太多的信息。我猜你正在尝试使用一个比你设计的代码要处理的大小更大的数字。Microsoft在其Visual Studio环境中有一个很好的调试器。也可以。当你说“太高”和“错误的数字”时,你并没有给我们太多的信息。作为猜测,我会想象你正在尝试使用一个比你设计的代码要处理的大小更大的数字。谢谢你的帮助,但我不明白实际数字=256*(2*AH)+(字节ptr缓冲区[ebx]-30h)@傻瓜亚当:很简单:AX
是(256*AH)+AL。或者用另一种符号: