I was looking through my old GitHub account the week and rediscovered my old 8080 emulator project I started last year. Out of boredom, I've decided to pick up the project again and see what I can do to progress it further.
As the project was correctly failing the build, the first order of business was to get the project building correctly and to start passing tests. When i last left it alone, the emulator was failing as the program was trying to write outside the bounds of memory. Debugging further, I noticed that this was because of this particular program code:
0x1A32: 1A MOV A, (DE)
0x1A33: 77 MOV (HL),A
0x1A34: 23 INC HL
0x1A35: 13 INC DE
0x1A36: 05 DEC B
0x1A37: C2 JNZ, 0x321A
It's a simple loop that copies into RAM. Once register B hits 0, we expect to jump to 0x321A. The underlying issue I forgot to add any logic for the carry bit or the zero bit for the INC/DEC commands. Since JNZ would never perform the jump, the program would continue to copy until it was outside the memory bounds. The fix was obvious: I just needed to implement zero and carry bits. Our logic for our DEC/INC commands than went from this
// 0x1D - DEC E
case 0x1D:
if(cpu->E == 0x00) {
cpu->E = 0xFF;
} else
cpu->E -= 1;
cpu->PC += 1;
break;
to this
// 0x1D - DEC E
case 0x1D:
cpu->FLAGS.C = 0x00;
cpu->FLAGS.Z = 0x00;
if(cpu->E == 0x00) {
cpu->E = 0xFF;
cpu->FLAGS.C = 0x01;
} else
cpu->E -= 1;
if(cpu->E == 0x00) {
cpu->FLAGS.Z = 0x01;
}
cpu->PC += 1;
break;
Compiling and running it on my local machines shows the program now runs correctly and the VM stops at the RET instruction which I have yet to implement. Hurray!