Search code examples
assemblyx86bit-manipulationcarryflageflags

How to set carry flag in specific bit in GPR without shifts / rotations?


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?


Solution

  • 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.