MASM - 舍入整数

时间:2017-05-07 18:06:35

标签: assembly x86 masm

在我的程序中,我试图计算两个整数的平均值,然后舍入数字。例如,如果平均值为-22.5,则将舍入为-23。 validInputs是从用户收集的有效输入的数量,并且始终是正整数,而validSum将始终是负整数,因为它只添加负整数。然而,当比较余数时,我没有得到正确的舍入结果,并且想知道为什么。

编辑:我将建议的更改设为-5,但仍然遇到相同的错误。我相信我的错误必定是一个逻辑问题。

mov     eax, validSum
cdq
mov     ebx, validInputs
idiv    ebx
mov     validAverage, eax
mov     intRemainder, edx
cmp     edx, -5 ; compare the remainder to -5
jg      display ; if greater than -5 we know not to round/decrement
dec     validAverage

1 个答案:

答案 0 :(得分:1)

如果你只是除以2,解决方案很容易。 IDIV在这种情况下只给出三个可能的余数:{-1,0.1},这意味着:

  • -1:总和为负数,小数点后面的数字为-0.5,平均值必须减1,即avg = avg + (-1)

  • 0:没有余数,平均值已经正确舍入,即avg = avg + 0

  • 1:总和为正数,余数为0.5,必须加1,即avg = avg +1

正如您所看到的,不需要进行冗长的比较,您可以将余下的EDX添加到EAX

; Only valid for EBX=2
mov     eax, validSum
cdq                                 ; EAX -> EDX:EAX
mov     ebx, validInputs
idiv    ebx                         ; EDX:EAX / EBX -> EAX remainder EDX
mov     validAverage, eax           ; Save result
add     validAverage, edx           ; Add -1 or 0 or 1
jmp     display                     ; End of Rounding

除此之外,余数与十进制数的小数部分无关。将它与5或-5直接比较是完全错误的。您必须先获得第一个小数位。在长时间的分工中你会添加"结尾为0,然后除以除数。同样在这里:乘以十(=最后加0)并除以EBX。现在你可以将结果除以5得到上面的三元组:{-1,0.1}

...
idiv    ebx                         ; EDX:EAX/EBX
mov     validAverage, eax           ; Save result

mov eax, edx
add eax, eax                        ; A quick way to multiply by 10
lea eax, [eax + eax * 4]            ;    EAX * 10 = EAX * 2 + EAX * 8
cdq                                 ; EAX -> EDX:EAX
idiv ebx                            ; EDX:EAX / EBX -> EAX remainder EDX
mov  ebx, 5
cdq                                 ; EAX -> EDX:EAX
idiv ebx
add validAverage, eax               ; Add -1 or 0 or 1
jmp     display                     ; End of Rounding

您可以将EAX*10/EBX/5转换为EAX*2/EBX

mov     eax, validSum
cdq                                 ; EAX -> EDX:EAX
mov     ebx, validInputs
idiv    ebx                         ; EDX:EAX / EBX -> EAX remainder EDX
mov     validAverage, eax           ; Save result

imul eax, edx, 2                    ; EAX = EDX * 2
cdq                                 ; EAX -> EDX:EAX
idiv ebx                            ; EDX:EAX / EBX
add validAverage, eax               ; Add -1 or 0 or 1

jmp display                         ; End of Rounding