ASM Flags
Evil twin of <FL+

Assembly Flags We've gone over the logical hodgepodge, so now we finally get to look at the assembly flags. Remember that these are not TSC flags! They are similar in function, however. All the ASM flags are 1-bit values stored in a special register. As mentioned in a much earlier lesson, that register is called the FLAGS. (wow, what originality!) Each bit of the 16-bit FLAGS register represents a flag, but some of them are unused. Here are 4 important ones: Z flag = Zero flag S flag = Sign flag C flag = Carry flag O flag = Overflow flag So, how are these flags "set"? Well, they are essentially set and reset after almost every mathematical instruction (including logic instructions), as well as CMP and other compare instructions: The Zero flag is set if the result of the last math or compare instruction was 0. If not, then it is reset. The Sign flag is set if the result of the last math or compare instruction was negative. If not, then it is reset. This is also called the "negative flag". The Overflow flag is set if the last result doesn't fit into the destination (it detects signed overflow). For example, if you're doing `ADD EAX,ECX` and EAX holds signed 7FFF0000 while ECX holds signed 5A0BC, then the answer, 8004A0BC, is too big to be a signed positive number, so it must instead be interpreted as a signed negative number, and the O flag will be set. Therefore, consider this flag set if a register's sign changes during a math operation. If the result wasn't too big, this flag is reset. The Carry flag tests for unsigned overflows, much like the Overflow flag checks for signed overflows. This will be set if the result of an addition is too big to fit in a destination. Likewise, it will be set if the result of a subtraction is negative. Precise Definition of the Jump Commands In reality, all of the conditional JMP commands are really just "jump if flag is set" or "jump if flag isn't set". CMP A,B = Affects the flags in the same way as SUB A,B, but it doesn't actually perform the subtraction. JE X = Jump to address X if flag Z is set. Same as JZ (jump if zero). JNE X = Jump to address X if flag Z is cleared. Same as JNZ (jump if not zero). JGE X = Jump to X if flag S and flag O are the same value. Same as JNL (jump if not less). JG X = Jump to X if flag S and flag O are the same value, and flag Z is not set. Same as JNLE (jump if not less or equal). JL X = Jump to X if flag S and flag O are different values. Same as JNGE (jump if not greater or equal). JLE X = Jump to X if flag S and flag O are different values, or if flag Z is set. Same as JNG (jump if not greater). JA X = Jump to address X if flag Z and flag C are cleared. Same as JNBE (jump if not below or equal). JB X = Jump to address X if flag C is set. Same as JC (jump carry) or JNAE (jump if not above or equal). JBE X = Jump to address X if flag C or flag Z is set. Same as JNA (jump if not above). JNB X = Jump to address X if flag C is cleared. Same as JNC (jump not carry) or JAE (jump if above or equal). Some Examples Now, I know my explanations for the overflow and carry flags were confusing, but I hope some examples will help.
    MOV EAX, 244
    CMP EAX, 244
    JE 490A00
    NOP
Now, will the above code jump to 490A00 or will it execute the `NOP` directly after `JMP 490A00`? You should be saying, "Duh. Of course it will jump to 490A00. Since EAX is guaranteed to hold 244, and 244 is equal to 244, the JE instruction will successfully perform a jump." But let's think of this in terms of flags: We store 244 to EAX. We "pretend" to subtract 244 from EAX, and we don't really do it. The result of the fake subtraction is 0. Because the last math result was 0, the Z flag is set. JE will only jump to its address if the Z flag is set. The Z flag is indeed set, so the jump is taken. That should make sense. The computer doesn't really understand that EAX is equal to 244. It just pretended to subtract 244 from EAX using the CMP instruction, saw that the result would have been 0, and set the Z flag. The next instruction just happens to check for the Z flag, so the jump is taken.
    MOV EAX, FFFFFFFF
    MOV ECX, 202
    ADD EAX, ECX
    JC 49F1DC
Now, this looks a bit insane. We are trying to use a conditional jump without using CMP! Oh noes! What will happen? But of course, we know what will happen, since we can check how the flags are set. The last math instruction was ADDing 202 to FFFFFFFF and storing the result to EAX. This will definitely set the carry flag: the result is too big to fit into EAX, and so it will just "wrap around" to 201. The JC instruction will successfully jump to 49F1DC because it sees the carry flag is set, so we're done. Navigation Previous Lesson: Logic Instructions Next Lesson: Equips and Collisions Table of Contents