我有以下代码,但我无法理解为什么如果我输入的数字太高,它会返回错误的数字。这可能是因为数据类型和分割和乘法,但我无法确切地解释为什么。如果你知道为什么我会感激你的帮助。
.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
答案 0 :(得分:2)
是的,您的返回值受最大值限制是合理的。这个最大值是255的BYTE
边界或65536的WORD
边界。让我逐一解释原因:
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
函数,该函数始终返回寄存器return
中的EAX
值。返回后,将32位返回值的低8位分配给byte ptr buffer+[ebx]
,从中减去30h
。然后,MOV
刚刚在AL
中修改的8位,以及AH
中保留的返回值中的8位作为块AX
到WORD
变量add [actualNumber],ax
。因此AH
源于EAX
返回值并且非常undefined
。如果它是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 actualNumber,ax
仅MOV
变量DX
的低16位被忽略,将结果限制为result % 65536
。因此,您的最大可能结果是MAX_WORD = 65535.其他所有内容都只会在AX
中为您提供模数。
在mov al, byte ptr buffer+[ebx]
覆盖此结果的低8位后,BYTE
指向buffer[ebx]
,然后从中减去30h
。请记住:结果的高8位仍然保留在AH中,即AX的高8位。
然后您(重新)使用actualNumber
将此值添加到变量add actualNumber,ax
。让我浓缩这最后两段:
Operation | AX |
| AL AH |
mov actualNumber,ax | ................ |
mov al, byte ptr buffer+[ebx] | ........ AH |
sub al,30h | ....-30h AH |
add actualNumber,ax | ................ |
因此,您正在修改AX
到AL
的低8位,然后将actualNumber
/ AH
的高8位添加到自身 - 实际上加倍AH
然后将其添加到actualNumber
,如下所示:
actualNumber = 256 * (2 * AH) + (byte ptr buffer[ebx]-30h) ; I doubt you want that ;-)
这些问题可能会导致与预期结果的偏差。