2016-04-15 58 views
0

我得到了下面的代码,但我无法弄清楚为什么如果输入的数字太高,它会返回错误的数字。这可能是因为数据类型和分割和相乘,但我不能确切地说明原因。如果你知道为什么我会很感激这个帮助。为什么如果我输入的数字变得很高,它会返回错误的数字

.586 
.model flat, stdcall 
option casemap :none 
.stack 4096 
extrn [email protected]: 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 [email protected] 
end  main 
+0

微软在其Visual Studio环境中有一个很好的调试器。 [Ollydbg](http://www.ollydbg.de/)也可以。 –

+0

当你说“太高”和“错误的数字”时,你真的不会给我们太多的帮助。“作为一种猜测,我会想象你正在尝试使用比你设计的代码处理的大小更大的数字。 –

回答

2

是的,您的回报值被最大值限制是合理的。这是最大的任一255​​边界或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是变量的低16位(DX被忽略,将结果限制为result % 65536)。所以你的最大可能的结果是MAX_WORD = 65535.其他的只会给你模AX

mov al, byte ptr buffer+[ebx]您覆盖这个结果与​​的低8位由buffer[ebx]指了指,然后减去其30h之后。请记住:结果的高8位仍保留在AH中,AX的高8位。

然后您(重新)将此值添加到变量actualNumberadd actualNumber,ax。让我来凝聚最后两个段落:

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 ;-) 

这些问题可能会导致与期望的结果有几个偏差。

+0

感谢您的帮助,但我不明白actualNumber = 256 *( 2 * AH)+(byte ptr buffer [ebx] -30h) – dummieadam

+0

@dummieadam:这很简单:'AX'是(256 * AH)+ AL或者用另一种表示法:'AX = AH * 256 + AL'。换句话说:像AX这样的16位数值由两个8位值(AH和AL)组成,而高位8位由2^8 =所以'AX(16位)= AH(8位)* 256 + AL(8位)'。 – zx485

相关问题