I've been working on a Game Boy emulator, and I've noticed that there are certain opcodes that exist that would never change any values, such as LD A, A
, LD B, B
, etc. and also AND A
. The first ones obviously don't change anything as they load the value of registers into the same registers, and since the AND
is being compared with the A
register, AND A
will always return A
. Is there any purpose for these operations, or are the essentially the same as NOP
after each cycle?

- 704
- 1
- 7
- 18

- 716
- 3
- 8
- 23
-
6I imagine they exist for the same reason you can write `mov eax, eax` in x86: it wasn't worth complicating the encoding space to use those encodings for something useful. (I'm not familiar enough with the Game Boy or z80 to say if these instructions have any hidden microarchitectural side effects, sorry.) – Jeffrey Bosboom Oct 17 '14 at 02:23
-
3This goes back to the 8008 processor, 1970. Simplicity was important, it only had 3500 transistors. The later 8080 and Z80 copied the instruction set design. No purpose to them, only to keep the instruction decoder logic simple. – Hans Passant Oct 19 '14 at 03:47
3 Answers
As Jeffrey Bosboom and Hans Passant pointed out on their comments, the reason is simplicity. More specifically hardware simplicity.
LD r,r'
instructions copy the content of source register (r'
) to destination register (r
). LD r,r'
opcodes follow this form:
-------------------------------
BIT | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-------------------------------
OPCODE | 0 | 1 | r | r' |
-------------------------------
Destination and source registers can assume these values:
-----------
| BIT | REG |
-----------
| 111 | A |
-----------
| 000 | B |
-----------
| 001 | C |
-----------
| 010 | D |
-----------
| 011 | E |
-----------
| 100 | H |
-----------
| 101 | L |
-----------
In order to implement these instructions in hardware we just need a multiplexer that receives bits 0-2 to select the source register and another multiplexer that receives bits 3-5 to select the destination register.
If you want to verify if bits 0-2 and bits 3-5 are pointing to the same register you would have to add more logic to the CPU. And as we all know, ressources were more limited in the 80's :P
Please note that loading instructions such as LD A,A
, LD B,B
, LD C,C
, LD D,D
, LD E,E
, LD H,H
, and LD L,L
behave like NOP
. However AND A
and OR A
DO NOT behave like NOP
, since they affect the flag register, and their execution might change the internal machine state.

- 1
- 1

- 7,986
- 4
- 45
- 57
-
4Working from a software perspective, it's easy to overlook the hardware that would have to be in place on the original system. Just what I was looking for, thanks. – Zach Brantmeier Oct 21 '14 at 21:54
-
1Actually (at least on Z80, gameboy's CPU is not Z80, maybe Z80 or 8080 like only ... missing many of Z80 features) the only exception is (HL) with LD, LD (HL),(HL) combination does not exist and it means HALT (so a totally different thing) instead. But (HL) reference is a bit special anyway even if it's among the normal LD r1,r2 block os opcodes. – LGB Oct 31 '14 at 14:48
Instructions like LD A,A
and AND A
may appear to be NOP
s but they might also change the processor flags and be used for testing the value of a register.
Be sure to check the instruction set documentation carefully for such side effects.

- 7,986
- 4
- 45
- 57

- 15,685
- 6
- 28
- 34
-
`AND A` is the idiomatic way to compare to zero if memory serves; it's one byte rather than two and fewer cycles as a result. – Tommy Oct 31 '14 at 02:27
-
1
There is actually purpose in AND A
(as well as OR A
) instruction -- it sets flag Z
when A
is zero and clears otherwise. So both AND A
and OR A
are frequently used for this purpose.

- 793
- 3
- 12
-
1They also unconditionally clear the carry flag, which is useful if you are using it to return a result (e.g. a function that returns a value but signals an error or exception condition by setting carry). – Simon Sellick Mar 16 '15 at 17:36