Flags

In this section, we will see new instructions at the same time as the flags, to help understand how instructions work with flags.

The f register

f being an 8-bit register, it has 8 bits. Bits 0-3 are always zero. Bits 4-7 are called C, H, N, and Z, in that order. Note that, to avoid confusing register c and flag c, flags sometimes get an "f" appended to them (eg. CF, ZF). However, that notation will not work when referencing the flags in the source code &emdash; it's only useful for discussion.

As always, each of these letters stands for something:

c
Carry
h
Half-carry
n
Add/Subtract (ok, this one doesn't make sense)
z
Zero

Remember that flags are just bits of the f register. As such, a flag is said to be set when its corresponding bit is 1. (It thus equates to "true" by law of non-zero, but that doesn't matter a lot here.)

Z - Zero

Z is the simplest flag of them all. It generally follows the rule of thumb "If the instruction's result was zero, then it's set; otherwise, it's reset." Simple enough. And to illustrate that, let's talk about inc and dec.

inc and dec

inc has a simple purpose - increment a register's value. The purpose of dec is left as an exercise for the most alert of our readers. There are two flavors of inc and dec: 8-bit inc/dec and 16-bit inc/dec. 8-bit inc/dec affects the Z flag as you'd expect: if the register holds 0 after the operation, Z is set. Otherwise, it's reset. Note that, obviously, overflow applies, as demonstrated below.

    ld b, $FF
    dec b
    ; B = $FE, Z reset
    inc b
    ; B = $FF, Z reset
    inc b
    ; B = $00, Z set
    inc b
    ; B = $01, Z reset
    dec b
    ; B = $00, Z set

    ld b, $FE
    ; B = $FE, Z set (keep in mind, `ld` doesn't affect flags!)
    inc b
    ; B = $FF, Z reset
    ld b, 0
    ; B = $00, Z reset

Remember how in the previous lesson, I said that [hl] basically was an 8-bit register? Well, it delivers: inc [hl] and dec [hl] are a thing! This directly modifies the byte in memory that hl points to, affecting flags.

Also, for future reference, note that inc and dec modify the H an N flags. Given how little importance they have, I won't explain how yet.

As for the 16-bit flavor of inc and dec, it takes any of the three 16-bit registers, and increments/decrements their content. The twist is, flags are preserved. All of them.

C - Carry

This one is also straightforward... or confusing, because different instructions make it work differently. The general rule is: it extends the current operation. Confused? Here's a slow start: remember in the Basic Concepts lesson, we talked about overflow, and I mentioned that "we don't have space to store that ninth bit"? Well, there isn't space to store it in the register itself, but since the carry extends the current operation, that ninth bit is stashed in the Carry bit/flag instead.

8-bit add

Here's a concrete example: now introducing the add instruction! It also comes in two flavors, but this will be discussed more in the next chapter. For now, we will consider add a, X, where X is either an 8-bit register, or an immediate 8-bit value. It basically takes a's content, adds X to that, and stores the result back in a. This updates both the Z and C flags. (And the H and N flags, but we'll see that later.)

    ld a, $EF
    ld b, $10

    add a, b
    ; A = $FF, Z reset, C reset
    add a, b
    ; A = $0F, Z reset, C set
    add a, b
    ; A = $1F, Z reset, C reset
    add a, $E1
    ; A = $00, Z set, C set
    add a, 0
    ; A = $00, Z set, C reset

We'll see different uses of the Carry flag in the upcoming lessons.

H & N - The BCD flags

These flags are updated by a lot of instructions, and they work in a kind of obtuse way... furthermore, they are used by exactly one instruction. What??!? Well, that instruction is pret~ty useful when doing Binary-Coded Decimal (BCD). That will be discussed in the next section, because it's simpler to explain what it does than how it works. Don't worry, there will still be a detailed explanation for those whose OCD is triggering like crazy right now.