Search code examples
assemblyx86conditional-statementsmasmeflags

How Does Setting/Unsetting MASM Flags Work


Set means flag value = 1 and Unset means flag value = 0

Now I understand there are several ways to set and unset flags in MASM, as follows:

test al,0 ; set Zero flag
and al,0 ; set Zero flag
or al,1 ; clear Zero flag

Same goes for Sign flag:

or al,80h ; set Sign flag
and al,7Fh ; clear Sign flag

To set the Carry flag, we use the STC instruction; to clear the Carry flag, we use CLC:

stc ; set Carry flag
clc ; clear Carry flag

To set the Overflow flag, we add two positive values that produce a negative sum. To clear the Overflow flag, we OR an operand with 0:

mov al,7Fh ; AL = +127
inc al ; AL = 80h (-128), OF=1
or eax,0 ; clear Overflow flag

The Overflow and Carry flags operations are self-understood and easy to grasp, but I find it hard to understand the mathematics behind setting the Zero/Sign flags. Any help is appreciated!

Thanks!


Solution

  • The whole point of using the flags is that they are a side effect of other operations - and you can test the result after the operation has occurred.

    So, for example, you can count down from 10 to 0 without explicitly testing for zero:

           mov cx, 10
    Again:
           ; Do some stuff, not changing cx
           dec cx
           jnz Again ; Go back to Again if not zero
    

    The "Do some stuff" happens ten times, because dec affects the Z flag.

    The reason that stc and clc exist is to help with multi-digit arithmetic. The C flag is used to keep track of "Carries" out of previous arithmetic, so that you can factor them into future operations:

    op1 dd  0x12345678 ; 32-bit value
    op2 dd  0x9abcdef0 ; 32-bit value
    
        mov ax,[op1+0] ; Get low word of op1
        mov dx,[op1+2] ; Get high word of op1
    
        add ax,[op2+0] ; Add in low word of op2
        adc dx,[op2+2] ; Add in high word of op2 - WITH CARRY!
    

    Because of these kinds of operations, you may need to pre-load C with 0 or 1 before starting on the algorithm. Hence clc and stc - and why no other (arithmetic) flags have a "set" or "clear" op-code.

    Note that there are other, non-arithmetic flags:

    • The D (direction) flag controls the direction of string instructions such as STOS and MOVS. Thus there are cld and std instructions.
    • The I (interrupt) flag controls whether interrupts are enabled or not. Thus there are cli and sti instructions.