x86 程序集:ADD/SUB/INC/DEC 没有溢出和分支
x86 assembly: ADD/SUB/INC/DEC without overflow and branching
在 x86 ASM 中,是否可以禁止在不带分支的情况下进行加法或减法时溢出?因此,例如,当从 0x01 中减去 0x02 时,它会设置 0x00 而不是 0xFF。
我认为这可能是不可能的,所以我也对这个问题的更严格形式的答案感兴趣,其中只有 0x01 added/subtracted。我有一个想法是这样的(OF 是溢出标志):
dec eax
add eax,OF
我不知道其他架构,但对于 i386,我找不到它的操作码,因为显然标志不能被解释为整数并用于算术运算。我找到了一个可行的解决方案,但仅在未使用较高字节时适用于最低字节:
dec ax
sub al,ah
xor ah,ah
有没有更好的方法来做到这一点,也许也适用于更一般的情况?
在递增1的情况下(使用add #1
,而不是inc
)你可以在之后sbc #0
实现饱和。与减 1 类似:使用 sub #1
后跟 adc #0
.
或者考虑使用 SSE,它支持在单个指令中进行饱和整数算术运算。
您可以在较新的处理器上使用 cmov
(条件 MOV)系列指令来避免在许多情况下发生分支,包括您描述的示例。如果标志值设置得当,这些指令的行为类似于常规 mov
,否则什么都不做。
但是:
I had an idea that goes like this (OF being the overflow flag)
这不是你想要的溢出标志;这表明该值溢出了使用 2 的补码表示的边界(因此对于 16 位字值,如果它变得小于 -32768 或大于 32767)。您似乎正在使用无符号数(并希望钳位为 0),所以您想要的是 carry 标志。
例如,如果有进位(如果结果从 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
在 x86 ASM 中,是否可以禁止在不带分支的情况下进行加法或减法时溢出?因此,例如,当从 0x01 中减去 0x02 时,它会设置 0x00 而不是 0xFF。
我认为这可能是不可能的,所以我也对这个问题的更严格形式的答案感兴趣,其中只有 0x01 added/subtracted。我有一个想法是这样的(OF 是溢出标志):
dec eax
add eax,OF
我不知道其他架构,但对于 i386,我找不到它的操作码,因为显然标志不能被解释为整数并用于算术运算。我找到了一个可行的解决方案,但仅在未使用较高字节时适用于最低字节:
dec ax
sub al,ah
xor ah,ah
有没有更好的方法来做到这一点,也许也适用于更一般的情况?
在递增1的情况下(使用add #1
,而不是inc
)你可以在之后sbc #0
实现饱和。与减 1 类似:使用 sub #1
后跟 adc #0
.
或者考虑使用 SSE,它支持在单个指令中进行饱和整数算术运算。
您可以在较新的处理器上使用 cmov
(条件 MOV)系列指令来避免在许多情况下发生分支,包括您描述的示例。如果标志值设置得当,这些指令的行为类似于常规 mov
,否则什么都不做。
但是:
I had an idea that goes like this (OF being the overflow flag)
这不是你想要的溢出标志;这表明该值溢出了使用 2 的补码表示的边界(因此对于 16 位字值,如果它变得小于 -32768 或大于 32767)。您似乎正在使用无符号数(并希望钳位为 0),所以您想要的是 carry 标志。
例如,如果有进位(如果结果从 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