Flags and Multi-Precision Arithmetic
CS 301 Lecture, Dr. Lawlor
The "EFLAGS" register on x86 stores a bunch of flags, as shown on page 73 of the Intel arch manual Volume
1. The important flags include:
- ZF-- The "zero flag". Set whenever the previous arithmetic result
was zero. Can be used by the "jz" (jump if last result was zero) or
"jnz" instructions. "je" (jump if equal) and "jne" (jump if not equal)
are just aliases of jz & jnz, because if the difference is zero,
then the two values are equal. For example, this code checks if the input is equal to 4:
extern read_input
call read_input
cmp eax,4
je equal
add eax, 20 ; If not equal, add
equal: ret; If equal, just return
- CF--The "carry flag". Set to
indicate the bit that carries out of an addition or subtraction.
Can be used by the "jc" (jump if carry flag is set) instruction.
Set by all the arithmetic instructions.
Can be added into another arithmetic operation with "adc" (add with
carry). For example, you can preserve the bit overflowing out of
a big add like this:
mov ecx, 0x8000ff00
add ecx, ecx
mov eax,0
adc eax,eax ; Adds eax, eax, and the carry flag together
"adc" is used in the compiler's implementation of the 64-bit "long
long" datatype, and in general in "multiple precision arithmetic"
software, like the GNU Multiple Precision Arithmetic Library. It'd also be used to implement overflow checking in a careful compiler, like
The carry and zero flags are also used by the unsigned comparison
instructions: "jb" (jump if unsigned below), "jbe" (jump if unsigned
below or equal), "ja" (jump if unsigned above), and "jae" (jump if
unsigned above or equal) in the usual way.
- SF-- The "sign flag", which indicates a negative signed result. Used together with OF to implement signed comparison.
- OF-- The "overflow flag". Set by subtract, add, and compare, and
used in the signed comparison instructions "jl" (jump if less than),
"jle" (jump if less than or equal to), "jg" (jump if greater than), and
"jge" (jump if greater than or equal to) instructions. If you
stare at it hard enough, you can read the definitions, work out exactly
what SF and OF do, and convince yourself they do the right thing.
They do.
You've also got to be aware of which instructions set which
flags. For example, the "cmp", "and" (bitwise AND), "sub", and
"add" instructions set all the flags; "inc" (increment by 1) and "dec"
(decrement by 1) set everything but CF; while "mov" and all the jump
instructions don't mess with the flags. It's easy to accidentally
overwrite flags you care about, if you leave too much stuff between the
time the flag is set and the time it's read!
You can actually look at the flags with the "lahf" instruction, which
copies the important bits of EFLAGS into register ah--that is, bits 8-16 of eax
get EFLAGS(SF:ZF:0:AF:0:PF:1:CF).
The various funky jump instructions, like "jc" (jump if CF is set), "jo" (jump if OF is set).
Note there's NO way to get at the flags, or to directly call the flag-using instructions in C! None!