This is a small interlude to talk about miscellaneous stuff. Take it easy, take a break, all that.
Note that while this is miscellanii, there are a few instructions introduced here. I still recommend you read this lesson.
On the topic of doing nothing
nop is one of the most powerful instructions of the GBz80's set. That's because it performs no operation! ...That's right, it's a 1-byte instruction that has no effect whatsoever, aside from wasting time. It has its uses, at times -- believe it or not, but sometimes we need to waste some time.
You may think that instructions such as
ld c, c or
ld a, a are useless, and basically the equivalent of
nop. Well, that's true, but we have two snowflakes there:
ld b, b and
ld d, d. While these instructions effectively do nothing, they're used by emulators (mostly) to notify the developer. Note that, as far as I'm aware, only two emulators support these: BGB and no$gmb.
ld b, b is a breakpoint inserted in the source code (BGB can break on those if the option is checked in the "Exceptions" menu), and
ld d, d allows printing debug messages to the console. Refer to BGB's manual for an explanation on how those work.
Note that while (some) emulators act specifically on these instructions, this is designed to be transparent (doing nothing) to emulators unaware of this, and to the actual console. You can also not use them.
a is the left operand to an arithmetic instruction (
and, etc.), it can be omitted. Thus,
add $38 is the same instruction as
add a, $38. Each programmer has their own rules about this;I personally use the short notation for everything but
add a, X. So, from now on, you will see things like
and b in this tutorial; remember that they're exactly the same as
and a, b!
When you want to check if
a equals zero, you may be tempted to use
cp 0. That's intuitive, sure, but there's a more efficient alternative:
and a (or
or a). This comes from the fact that if B is a bit, then
B and B = B. (
0 and 0 = 0,
1 and 1 = 1; note that this works for
or as well). Thus, if all bits in
a are reset, then
a = 0, thus the Z flag will be set. You may also notice that this affects the flags in exactly the same way (C reset, Z set).
Now, if you wanted to set
a to 0, you would probably do
ld a, 0. Again, there's a more efficient way:
xor a. This is because 0 xor 0 = 0, and 1 xor 1 = 0. Thus, every bit of
a will be xor'd with itself, which yields 0, for all bits. Now, there's a pretty big difference with
ld a, 0: that one preserves the flags, whereas
xor a resets C and sets Z. (It's also a pretty good way of setting the Z flag.)
Playin' with C
You can play very easily with the carry flag. Two instructions are entirely dedicated to it:
scf sets the carry
ccf complements (inverts) the carry flag. Neither of these instructions affect other flags or any registers. Now, if you wanted to reset the carry, you may think of doing
ccf, but there's a simpler solution:
and a. Remember that this instruction clears the carry, too... but it alters the Z flag, so it's not always applicable.