I'm writing a program in NASM for Intel 80386 processor and i need to set the value of carry flag in a specific bit in GPR (general purpose register) without changing other bits in register.
Are there any possibility of doing so without using shifts/rotations of any kind?
One branch-free way of doing this would be to fill a scratch register with the carry flag, mask for the bit you want, then or it with your target register.
Using EAX
as scratch (taking this as 32-bit values being manipulated):
sbb eax, eax
and eax, 1 << 16 ; Adjust bitshift in constant for the desired bit. Multiple bits can be used.
If the carry flag is unset, sbb
will do eax = eax - eax = 0
. If the carry flag is set, sbb
will do eax = eax - (eax + 1) = -1
, so all bits are set. The desired bit(s) is/are then masked in.
After that, you need to set the appropriate bit(s) in the target. If the bit is in an initial known state, this could be simplified. Using EBX
as target:
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
Depending on what previously happened to the scratch register (EAX
here) it might be worth looking at some optimization information like https://www.agner.org/optimize/. Some processors will recognize that the new value of EAX
doesn't depend on the old value, some will see it as having a (false) dependency on that old value.
After looking at it, the document "Optimizing subroutines in assembly language" mentions the above sbb
trick in the section "Replacing conditional jumps with bit-manipulation instructions".
Using EAX
(the accumulator) as the scratch register will result in smaller code size.