Nasm-乘以2的值会产生奇怪的结果

问题描述 投票:0回答:1

编辑:我正在使用this计算器检查结果,但似乎计算器本身在计算错误的值,导致了这个问题。

[使用mul指令时,我注意到将2个高数字相乘会导致错误的值。示例:

mov eax, 0ffffffffh
mov ebx, 0ffffffffh
mul ebx
; eax:00000001 I expected eax to be 0
; edx:FFFFFFFE

mov eax, 0ffffff00h
mov ebx, 0ffffffffh
mul ebx
; eax:00000100 I expected eax also to be 0
; edx:FFFFFEFF

我知道-1 * -11ffffffffh为负1。但是,将这两个数字以无符号乘法相乘不会得到1,还是这样?其他示例也是如此。

同样在使用imul指令时,我也会得到奇数,但我认为这是因为有符号乘法:

mov eax, 0fffffff0h
mov ebx, 5
imul ebx
; eax:FFFFFFB0
; edx:FFFFFFFF ; I expected edx to be 4
assembly x86 multiplication cpu-registers twos-complement
1个回答
1
投票

您的结果正常,您的期望是错误的。 IDK产生了您的错误期望,但32位mul的64位结果出现在EDX:EAX中。

[来自在线计算器,大概使用了Javascript编号,即带有53位尾数的mul精度浮点,它将double舍入到最接近的可表示双精度值,即0xfffffffe00000001

对于带符号的情况,您使用的计算器完全错误,希望它将您的输入解释为32位2的补码。


乘法结果的下半部分与您是否将输入解释为有符号无关,因此,作为快捷方式,我们可以使用0xfffffffe00000000在此处获得下半部分。 (这就是为什么英特尔只费心为-1 * -1 = 1(例如imul)添加有效的非扩展表格)。

[如果简单地在像imul eax, edx, -1这样的扩展精度计算器中试用(在Ubuntu中打包为calc,在Arch中打包为calc):

apcalc

因此,这确认了CPU的结果。请记住,和奇数乘以一个奇数就是一个奇数,因此也可以以这种方式排除对calc的EAX = 0猜测。


对于带符号,使用任意精度计算器有点棘手:

; base2(16)    // ask for hex output as well as decimal

; 0x0ffffffff ^ 2
        18446744065119617025 /* 0xfffffffe00000001 */

; 0x0ffffff00 * 0x0ffffffff
        18446742969902956800 /* 0xfffffeff00000100 */

那个小的无符号数当然分成0xffffffff * 0xffffffff; (0xfffffff0 - 2^32) * 5 -80 /* -0x50 */ ; . + 2^64 // get the 64-bit 2's complement bit-pattern for that negative number 18446744073709551536 /* 0xffffffffffffffb0 */ ,而EDX只是全数,与EAX的高位相同,因为这是符号扩展的工作方式。

© www.soinside.com 2019 - 2024. All rights reserved.