x86程序集:ADD / SUB / INC / DEC没有溢出和分支

时间:2015-07-11 09:06:05

标签: assembly integer-overflow

在x86 ASM中,在没有分支的情况下添加或减去时是否可以禁止溢出?因此,例如,当从0x01中减去0x02时,它将设置0x00而不是0xFF。

我希望这可能是不可能的,所以我也对这个问题的限制形式的答案感兴趣,其中只增加/减去0x01。我有一个这样的想法(OF是溢出标志):

dec eax
add eax,OF

我不知道其他架构,但是对于i386,我找不到这样的操作码,因为显然标志不能被解释为整数并用于算术运算。我找到了一个可行的解决方案,但仅在未使用高字节时的最低字节:

dec ax
sub al,ah
xor ah,ah

有没有更好的方法来做到这一点,也许还有一种适用于更一般的情况?

2 个答案:

答案 0 :(得分:5)

如果递增1(使用add #1,而非inc),您可以sbc #0之后实现饱和度。同样,按1递减:使用sub #1后跟adc #0

或者考虑使用SSE,它支持在单个指令中对整数算术运算进行饱和。

答案 1 :(得分:4)

您可以在较新的处理器上使用cmov条件MOV )系列指令,以避免在许多情况下进行分支,包括您描述的示例。如果适当地设置了标志值,则这些指令的行为类似于常规mov

请参阅http://www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc35.htm

然而:

  

我有一个这样的想法(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