我正在使用x86 Assembly,我已经满足了使用MUL
指令的需要。
我的代码片段曾经是这样的:
mov al, <some_number>
mul bl
add al, [edi]
mov [edi], al
如果<some_number>
是在此程序集片段外定义的常量,则它可以是正或负数。 bl
寄存器在代码的前面设置,它总是正的(因为只要适合它就会溢出/下溢)。我也可以将最后两个语句优化到add [edi], al
,但我不是100%肯定所以我不会那样做。
所以我的程序遇到了未定义的行为,在这种情况下是一个无限循环,在长时间检查可能出错之后,我认为我必须使用IMUL
,因为<some_number>
可能是否定的。
但现在它仍然不起作用。然后我再次查看手册,我看到mul bl
实际上将结果存储在ax
中。所以我在ax
中有一个已签名的结果,而我希望al
中的无符号(带溢出/下溢)结果。
所以我的问题是:如何将ax
中的签名结果转换为al
中的无符号结果?基本上与符号扩展相反。
注意:我在这里也包含了我的思考过程,因为我很可能不是按照预期做事,因此到目前为止我找不到答案。
答案 0 :(得分:3)
我无法正确理解问题以及评论中的后续行动。如果这根本不是答案,请告诉我。
我也发现这个答案可能是@Jose的答案,所以我正在考虑删除它,特别是如果我发现我误解了这个问题。
使用imul bl
,我们要么:
AL
(但结果是符号扩展为AX
)。 AL
。在后一种情况下你必须选择做什么 通常,您必须将结果缩放回8位,这可以像解决比例2 16 一样简单:2 8 = AX : AL AL 或者可以更多地参与(包括根本不是缩放或任何线性操作)。
在前一种情况下,我们需要计算结果的绝对值
由于案例1假设结果符合AL
,因此寄存器AH
全部为零或全部为1,与AL
的符号位匹配。
imul bl ;Original code
xor al, ah ;NOT AL iif the result is negative
sub al, ah ;AL = AL - (-1) = AL + 1 iif the result is negative
这利用了众所周知的身份,在两个补语中, neg(x)= not(x)+ 1 。
答案 1 :(得分:1)
这是我在一个例子中的观点:如果乘法的结果为负,你NEG
,如果它是正数你不NEG
它(我在运行这个代码)我的一个编译器):
mov bl, -5 ;◄■■ NEGATIVE NUMBER.
mov al, 10
imul bl ;◄■■ AX = -50 (0xFFCE).
cmp ax, 0
jl negative ;◄■■ IF AX < 0 JUMP TO NEGATIVE.
jmp continue ;◄■■ IF AX >= 0 SKIP NEGATIVE.
negative:
neg ax ;◄■■ AX => POSITIVE (0xFFCE => 0x32).
continue: