如何在没有移位/旋转的情况下在GPR的特定位设置进位标志?

我正在为 Intel 80386 处理器在 NASM 中编写程序,我需要在 GPR(通用寄存器)的特定位中设置进位标志的值,而不更改寄存器中的其他位。

是否有可能在不使用任何类型的移位/旋转的情况下这样做?

回答

这样做的一种无分支方法是用进位标志填充临时寄存器,掩码您想要的位,然后或用您的目标寄存器填充它。

使用EAX如划痕(以此为正被操纵的32位的值):

sbb eax, eax
and eax, 1 << 16  ; Adjust bitshift in constant for the desired bit. Multiple bits can be used.

如果未设置进位标志,sbb将执行eax = eax - eax = 0. 如果设置了进位标志,sbb将会执行eax = eax - (eax + 1) = -1,所以所有位都被设置。然后将所需的位屏蔽。

之后,您需要在目标中设置适当的位。如果该位处于初始已知状态,则这可以简化。使用EBX为目标:

and ebx, ~(1 << 16)  ; Same value at before. This doesn't need to be a shifted bit, it could be a number.
or  ebx, eax

根据之前发生在临时寄存器上的情况(EAX此处),可能值得查看一些优化信息,例如https://www.agner.org/optimize/。一些处理器会认识到新值EAX不依赖于旧值,一些处理器会认为它对旧值有(错误的)依赖。

看了之后,文档“Optimizing subroutines in assembly language”sbb在“用位操作指令替换条件跳转”一节中提到了上述技巧。

使用EAX(累加器)作为暂存寄存器将导致更小的代码大小。

  • Also consider using `cmovc` to shorten the critical path latency.

以上是如何在没有移位/旋转的情况下在GPR的特定位设置进位标志?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>