在x86 ASM中,在没有分支的情况下添加或减去时是否可以禁止溢出?因此,例如,当从0x01中减去0x02时,它将设置0x00而不是0xFF。
我希望这可能是不可能的,所以我也对这个问题的限制形式的答案感兴趣,其中只增加/减去0x01。我有一个这样的想法(OF是溢出标志):
dec eax
add eax,OF
我不知道其他架构,但是对于i386,我找不到这样的操作码,因为显然标志不能被解释为整数并用于算术运算。我找到了一个可行的解决方案,但仅在未使用高字节时的最低字节:
dec ax
sub al,ah
xor ah,ah
有没有更好的方法来做到这一点,也许还有一种适用于更一般的情况?
答案 0 :(得分:5)
如果递增1(使用add #1
,而非inc
),您可以sbc #0
之后实现饱和度。同样,按1递减:使用sub #1
后跟adc #0
。
或者考虑使用SSE,它支持在单个指令中对整数算术运算进行饱和。
答案 1 :(得分:4)
您可以在较新的处理器上使用cmov
(条件MOV )系列指令,以避免在许多情况下进行分支,包括您描述的示例。如果适当地设置了标志值,则这些指令的行为类似于常规mov
。
然而:
我有一个这样的想法(OF是溢出标志)
这不是你想要的溢出旗帜;这表示该值溢出了使用2的补码表示的边界(因此对于16位字值,如果它变得小于-32768或大于32767)。您似乎使用无符号数字(并希望将钳位设置为0),因此您需要的是进位标记。
例如,如果有进位(如果结果包含0到0xFF),则可以使用CMOVC
加载新值。
sub ax, 1
xor bx, bx
cmovc ax, bx
这在减去任何值时都有效。然而,事实证明,如果你只想要减量,有一种更简单的方法。您可以减去1,然后使用完全相同的指令添加0 +进位:
sub ax, 1
adc ax, 0
请注意,您无法使用dec
指令代替sub
,因为dec
不会影响进位标记。
如果采用另一种方式(添加),则使用sbb
代替adc
(当然还有add
代替sub
)。对于一般情况,您可以执行以下操作:
add ax, 1
mov bx, 0FFFFh
cmovc ax, bx