In this section, we will see new instructions at the same time as the flags, to help understand how instructions work with flags.
f being an 8-bit register, it has 8 bits. Bits 0-3 are always zero. Bits 4-7 are called
Z, in that order. Note that, to avoid confusing register
c and flag
c, flags sometimes get an "
f" appended to them (eg.
ZF). However, that notation will not work when referencing the flags in the source code — it's only useful for discussion.
As always, each of these letters stands for something:
- Add/Subtract (ok, this one doesn't make sense)
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 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
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
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
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.
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.