2015-07-11 17 views
1

在x86 ASM中,添加或减去分支时是否可以禁止溢出?因此,例如,当从0x01减去0x02时,它将设置0x00而不是0xFF。x86汇编:没有溢出和分支的ADD/SUB/INC/DEC

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

dec eax 
add eax,OF 

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

dec ax 
sub al,ah 
xor ah,ah 

有没有更好的方式来做到这一点,说不定这也适用于更一般的情况?

回答

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

但是:

我有一个想法,是这样的(是的溢出标志)

这不是你想要的溢出标志;表示该值使用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不影响进位标志的替代品。

对于走另一条路(加法),你代替使用sbbadc(当然add到位的sub)。对于一般情况下,你可以这样做:

add ax, 1 
mov bx, 0FFFFh 
cmovc ax, bx 
+0

我不认为一般情况下只需三条指令即可解决。很好的回答,谢谢。 –

5

在递增1的情况下(使用add #1而不是inc),然后您可以仅使用sbC#0来实现饱和度。类似地,递减1:使用sub #1后跟adC#0

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

+2

_“在1递增的情况下......” _只要该增量不使用'INC'完成,因为'INC'没有按不影响进位标志。 – Michael

+0

@迈克尔:谢谢 - 好点 - 回答更新。 –