Link Search Menu Expand Document

Intel 8080 CPU emulator

Altair 8800 originally came with processor Intel 8080. It is an 8-bit microprocessor, from 1974. The initial clock frequency was 2 MHZ. This processor was one of the first general-purpose and widespread processors, used not only in calculators but also in first personal computers. One of the key roles why this CPU become so popular is that Gary Killdall targeted his CP/M to this CPU; and CP/M was de facto a “standard” in personal computers those days.

Main features of the emulator include:

  • Threaded-dispatch combined with interpretation as emulation technique,
  • Correct real timing of instructions,
  • Ability to set clock frequency manually at run-time,
  • Emulation of all instructions including interrupts,
  • Disassembler implementation,
  • Ability to “dump” instruction history to console at run-time,
  • Support of breakpoints,
  • Ability of communication with up to 256 I/O devices,
  • Status window shows all registers, flags, and run-time frequency.

Configuration file

The following table shows all the possible settings of Intel 8080 CPU plugin:

Name Default value Valid values Description
printCode false true / false Whether the emulator should print executed instructions, and its internal state to console (dump)
printCodeUseCache false true / false If printCode is set to true, then a cache will be used which remembers already visited blocks of code so the instruction dump will not be bloated with infinite loops

Dumping executed instructions

The CPU offers a unique feature, which is the ability to dump executed instructions as a sequence to the console. When enabled, then each executed instruction - together with the content of flags and registers values after the execution is printed. This feature might be extremely useful in two cases:

  1. Reverse engineering of some unknown software
  2. It allows us to build tools for automatic checking of register values during the emulation when performing automatic emulation.

To enable this feature, please see the section “Configuration file”.

For example, let’s take one example which computes a reverse text:

; Print reversed text

org 1000

dcx sp       ; stack initialization (0FFFFh)

lxi h,text1
call putstr  ; print text1
lxi d,input  ; address for string input
call getline ; read from keyboard

lxi b,input

mvi d,0      ; chars counter

char_loop:
ldax b
inx b        ; bc = bc+1
cpi 10       ; end of input?
jz char_end
cpi 13
jz char_end

inr d        ; d =d+1
jmp char_loop
char_end:

dcx b        ;  bc = bc-1
dcx b

call newline

char2_loop:
ldax b
call putchar

dcx b

dcr d
jz char2_end

jmp char2_loop
char2_end:


hlt

include 'include\getchar.inc'
include 'include\getline.inc'
include 'include\putstr.inc'
include 'include\putchar.inc'
include 'include\newline.inc'

text1: db 'Reversed text ...',10,13,'Enter text: ',0
text2: db 10,13,'Reversed: ',0
input: ds 30

When the program is being run, and the dump instructions feature is turned on, on console you can see the following output:

0000 | PC=03e8 |       dcx SP |        3B  || regs=00 00 00 00 00 00 00 00  | flags=      | SP=ffff | PC=03e9
0001 | PC=03e9 |  lxi HL, 485 |  21 85 04  || regs=00 00 00 00 04 85 00 00  | flags=      | SP=ffff | PC=03ec
0001 | PC=03ec |     call 46D |  CD 6D 04  || regs=00 00 00 00 04 85 00 00  | flags=      | SP=fffd | PC=046d
0002 | PC=046d |     mov A, M |        7E  || regs=00 00 00 00 04 85 00 52  | flags=      | SP=fffd | PC=046e
0002 | PC=046e |       inx HL |        23  || regs=00 00 00 00 04 86 00 52  | flags=      | SP=fffd | PC=046f
0003 | PC=046f |        cpi 0 |     FE 00  || regs=00 00 00 00 04 86 00 52  | flags=      | SP=fffd | PC=0471
0004 | PC=0471 |           rz |        C8  || regs=00 00 00 00 04 86 00 52  | flags=      | SP=fffd | PC=0472
0005 | PC=0472 |       out 11 |     D3 11  || regs=00 00 00 00 04 86 00 52  | flags=      | SP=fffd | PC=0474
0006 | PC=0474 |      jmp 46D |  C3 6D 04  || regs=00 00 00 00 04 86 00 52  | flags=      | SP=fffd | PC=046d
0006 | PC=046d |     mov A, M |        7E  || regs=00 00 00 00 04 86 00 65  | flags=      | SP=fffd | PC=046e
0024 | Block from 0474 to 03EF; count=184
0024 | PC=03ef |  lxi DE, 4B2 |  11 B2 04  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=ffff | PC=03f2
0025 | PC=03f2 |     call 428 |  CD 28 04  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=0428
0025 | PC=0428 |     mvi C, 0 |     0E 00  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=042a
0025 | PC=042a |        in 10 |     DB 10  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=042c
0026 | PC=042c |        ani 1 |     E6 01  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=042e
0026 | PC=042e |       jz 42A |  CA 2A 04  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=042a
0027 | PC=042a |        in 10 |     DB 10  || regs=00 00 04 b2 04 a5 00 00  | flags= Z P  | SP=fffd | PC=042c
1548 | Block from 042E to 0431; count=181125
1548 | PC=0431 |        in 11 |     DB 11  || regs=00 00 04 b2 04 a5 00 68  | flags=      | SP=fffd | PC=0433
1548 | PC=0433 |        cpi D |     FE 0D  || regs=00 00 04 b2 04 a5 00 68  | flags=      | SP=fffd | PC=0435
1548 | PC=0435 |       jz 461 |  CA 61 04  || regs=00 00 04 b2 04 a5 00 68  | flags=      | SP=fffd | PC=0438
1548 | PC=0438 |        cpi A |     FE 0A  || regs=00 00 04 b2 04 a5 00 68  | flags=      | SP=fffd | PC=043a
1549 | PC=043a |       jz 461 |  CA 61 04  || regs=00 00 04 b2 04 a5 00 68  | flags=      | SP=fffd | PC=043d
1549 | PC=043d |        cpi 8 |     FE 08  || regs=00 00 04 b2 04 a5 00 68  | flags=  AP  | SP=fffd | PC=043f
1549 | PC=043f |      jnz 459 |  C2 59 04  || regs=00 00 04 b2 04 a5 00 68  | flags=  AP  | SP=fffd | PC=0459
1549 | PC=0459 |       out 11 |     D3 11  || regs=00 00 04 b2 04 a5 00 68  | flags=  AP  | SP=fffd | PC=045b
1549 | PC=045b |      stax DE |        12  || regs=00 00 04 b2 04 a5 00 68  | flags=  AP  | SP=fffd | PC=045c
1549 | PC=045c |       inx DE |        13  || regs=00 00 04 b3 04 a5 00 68  | flags=  AP  | SP=fffd | PC=045d
1549 | PC=045d |        inr C |        0C  || regs=00 01 04 b3 04 a5 00 68  | flags=      | SP=fffd | PC=045e
1549 | PC=045e |      jmp 42A |  C3 2A 04  || regs=00 01 04 b3 04 a5 00 68  | flags=      | SP=fffd | PC=042a
1550 | PC=042a |        in 10 |     DB 10  || regs=00 01 04 b3 04 a5 00 00  | flags=      | SP=fffd | PC=042c
2940 | Block from 045E to 0461; count=267777
2940 | PC=0461 |     mvi A, A |     3E 0A  || regs=00 05 04 b7 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=0463
2940 | PC=0463 |      stax DE |        12  || regs=00 05 04 b7 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=0464
2940 | PC=0464 |       inx DE |        13  || regs=00 05 04 b8 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=0465
2940 | PC=0465 |     mvi A, D |     3E 0D  || regs=00 05 04 b8 04 a5 00 0d  | flags= ZAP  | SP=fffd | PC=0467
2940 | PC=0467 |      stax DE |        12  || regs=00 05 04 b8 04 a5 00 0d  | flags= ZAP  | SP=fffd | PC=0468
2940 | PC=0468 |       inx DE |        13  || regs=00 05 04 b9 04 a5 00 0d  | flags= ZAP  | SP=fffd | PC=0469
2940 | PC=0469 |     mvi A, 0 |     3E 00  || regs=00 05 04 b9 04 a5 00 00  | flags= ZAP  | SP=fffd | PC=046b
2941 | PC=046b |      stax DE |        12  || regs=00 05 04 b9 04 a5 00 00  | flags= ZAP  | SP=fffd | PC=046c
2941 | PC=046c |          ret |        C9  || regs=00 05 04 b9 04 a5 00 00  | flags= ZAP  | SP=ffff | PC=03f5
2941 | PC=03f5 |  lxi BC, 4B2 |  01 B2 04  || regs=04 b2 04 b9 04 a5 00 00  | flags= ZAP  | SP=ffff | PC=03f8
2941 | PC=03f8 |     mvi D, 0 |     16 00  || regs=04 b2 00 b9 04 a5 00 00  | flags= ZAP  | SP=ffff | PC=03fa
2941 | PC=03fa |      ldax BC |        0A  || regs=04 b2 00 b9 04 a5 00 68  | flags= ZAP  | SP=ffff | PC=03fb
2941 | PC=03fb |       inx BC |        03  || regs=04 b3 00 b9 04 a5 00 68  | flags= ZAP  | SP=ffff | PC=03fc
2941 | PC=03fc |        cpi A |     FE 0A  || regs=04 b3 00 b9 04 a5 00 68  | flags=      | SP=ffff | PC=03fe
2941 | PC=03fe |       jz 40A |  CA 0A 04  || regs=04 b3 00 b9 04 a5 00 68  | flags=      | SP=ffff | PC=0401
2942 | PC=0401 |        cpi D |     FE 0D  || regs=04 b3 00 b9 04 a5 00 68  | flags=      | SP=ffff | PC=0403
2942 | PC=0403 |       jz 40A |  CA 0A 04  || regs=04 b3 00 b9 04 a5 00 68  | flags=      | SP=ffff | PC=0406
2942 | PC=0406 |        inr D |        14  || regs=04 b3 01 b9 04 a5 00 68  | flags=      | SP=ffff | PC=0407
2942 | PC=0407 |      jmp 3FA |  C3 FA 03  || regs=04 b3 01 b9 04 a5 00 68  | flags=      | SP=ffff | PC=03fa
2942 | PC=03fa |      ldax BC |        0A  || regs=04 b3 01 b9 04 a5 00 65  | flags=      | SP=ffff | PC=03fb
2942 | Block from 0407 to 040A; count=36
2942 | PC=040a |       dcx BC |        0B  || regs=04 b7 05 b9 04 a5 00 0a  | flags= ZAP  | SP=ffff | PC=040b
2943 | PC=040b |       dcx BC |        0B  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=ffff | PC=040c
2943 | PC=040c |     call 47A |  CD 7A 04  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=047a
2943 | PC=047a |     mvi A, A |     3E 0A  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=047c
2943 | PC=047c |     call 477 |  CD 77 04  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=fffb | PC=0477
2943 | PC=0477 |       out 11 |     D3 11  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=fffb | PC=0479
2943 | PC=0479 |          ret |        C9  || regs=04 b6 05 b9 04 a5 00 0a  | flags= ZAP  | SP=fffd | PC=047f
2943 | PC=047f |     mvi A, D |     3E 0D  || regs=04 b6 05 b9 04 a5 00 0d  | flags= ZAP  | SP=fffd | PC=0481
2943 | PC=0481 |     call 477 |  CD 77 04  || regs=04 b6 05 b9 04 a5 00 0d  | flags= ZAP  | SP=fffb | PC=0477
2943 | PC=0477 |       out 11 |     D3 11  || regs=04 b6 05 b9 04 a5 00 0d  | flags= ZAP  | SP=fffb | PC=0479
2943 | Block from 0481 to 0484; count=2
2943 | PC=0484 |          ret |        C9  || regs=04 b6 05 b9 04 a5 00 0d  | flags= ZAP  | SP=ffff | PC=040f
2944 | PC=040f |      ldax BC |        0A  || regs=04 b6 05 b9 04 a5 00 6f  | flags= ZAP  | SP=ffff | PC=0410
2944 | PC=0410 |     call 477 |  CD 77 04  || regs=04 b6 05 b9 04 a5 00 6f  | flags= ZAP  | SP=fffd | PC=0477
2944 | PC=0477 |       out 11 |     D3 11  || regs=04 b6 05 b9 04 a5 00 6f  | flags= ZAP  | SP=fffd | PC=0479
2944 | Block from 0410 to 0413; count=2
2944 | PC=0413 |       dcx BC |        0B  || regs=04 b5 05 b9 04 a5 00 6f  | flags= ZAP  | SP=ffff | PC=0414
2944 | PC=0414 |        dcr D |        15  || regs=04 b5 04 b9 04 a5 00 6f  | flags=  A   | SP=ffff | PC=0415
2944 | PC=0415 |       jz 41B |  CA 1B 04  || regs=04 b5 04 b9 04 a5 00 6f  | flags=  A   | SP=ffff | PC=0418
2944 | PC=0418 |      jmp 40F |  C3 0F 04  || regs=04 b5 04 b9 04 a5 00 6f  | flags=  A   | SP=ffff | PC=040f
2944 | PC=040f |      ldax BC |        0A  || regs=04 b5 04 b9 04 a5 00 6c  | flags=  A   | SP=ffff | PC=0410
2945 | Block from 0418 to 041B; count=31
2945 | PC=041b |          hlt |        76  || regs=04 b1 00 b9 04 a5 00 68  | flags= ZAP  | SP=ffff | PC=041c

The dump format consists of lines, each line represents one instruction execution. The line is separated by | chars, splitting it into so-called sections. Sections before the sequence || represent the state before instruction execution, and sections after it represent the state after instruction execution. Particular sections are described in the following table.

Column Description
1 Timestamp from program start (seconds)
2 Program counter before instruction execution
3 Disassembled instruction
4 Instruction opcodes
  Now follows the state after instruction execution
5 Register values (B,C,D,E,H,L, reserved (always 0), A)
6 Flags
7 Stack pointer register (SP)
8 Program counter after instruction execution