Inside the CPU: Registers and Machine Code
Now that we understand the Von Neumann model, let’s zoom in on the CPU itself. At the heart of the CPU are small, fast memory units called registers. Here are some common registers found in every cpu, among others:
- Program Counter (PC): Holds the address of the next instruction to execute.
- Instruction Register (IR): Holds the currently executing instruction.
- Accumulator (ACC): A general-purpose register for arithmetic/logical operations.
- Status Flags: Indicate things like zero result, overflow, or carry.
Machine Code: The CPU's Native Language
Every CPU has its own instruction set — a list of binary operations it understands. These instructions are called machine code. Higher-level languages (like Java or Python) are eventually compiled or interpreted into these binary instructions. Machine code is rarely read or edited by humans directly. Usually we represent CPU instructions using a language called assembly language. Since every CPU architecture has it's own instruction set, each CPU architecture also has it's own assembly language. Examples are: x86-64 assembly, ARMv9 assembly, etc.
MVI A, 48h ; Load 0x48 into Accumulator
OUT 11h ; Output value to port 1
HLT ; Halt execution
Machine code:
3E 48 D3 11 76
Explanation
3E: Opcode for "MVI A, immediate"48: The value to loadD3: Opcode for "OUT"11: Output port76: Opcode for "HLT"
Altair 8800: A Hands-On Example
The Altair 8800 (1975) used an Intel 8080 CPU. Programming it involved toggling switches on the front panel to enter raw machine code and binary data into RAM.
Want to Try It?
You can experiment with Altair emulation using Altair 8800 Emulator or SIMH.
Hello world!
A longer example, this assumes that the "Hello world!" text is loaded at memory address 0100h and closed of with a NUL character.
0: LXI H,0100h ; Load register H with the memory address of our message 3: MOV A,M ; Load the accumulator with the byte in memory, as pointed to by register H 4: CPI 00h ; Compare the accumulator to 0, this will set or unset the Zero Flag in the status register 6: JZ 000Fh ; If the Zero Flag is set, jump to address 15 (F) 9: OUT 11h ; Output the accumulator to port 11h (which would be the Teletype) B: INX H ; Increase register H to have it point to the next byte C: JMP 0003h ; Jump to memory address 3 F: HLT ; Stop execution
Here is the same code in Java:
byte[] data = "Hello world!\n\0".getBytes();
int H;
byte A;
H = 0;
while (true) {
A = data[H];
if (A == 0) break;
System.out.write(A);
H++;
}