The Shift to System Programming
Up until now, our code has been generic. System programming requires us to stop using symbolic addresses (like PRINT_STRING_ADDR
) and start using absolute hardware addresses specific to our target machine.
Key System-Specific Areas We Must Identify:
- Program Load Address (ORG): Where our code starts.
- Screen Memory: The RAM address where display data is stored.
- I/O Ports: The addresses for keyboard, sound, and display chips.
Setting the Origin (ORG) and Stack (SP)
Before execution begins, the assembler must know where in memory the program will be placed.
Example: A Common Load Address In many 8-bit systems, user code starts at a safe location, far from the operating system ROM.
ORG 8000H ; Code starts at 32768 decimal
; Set the Stack Pointer (SP) to the highest available RAM address
LD SP, FFFFH ; The stack grows *downward* from this address
Locating Screen Memory
On many retro systems, the visible screen content is a fixed area of RAM. We must calculate the exact starting address and size.
Example: Standard Screen Memory
Assume a screen buffer begins at address 4000H
and is 6144
bytes long.
LD HL, 4000H
loads the pointer to the top-left pixel/character.
Writing Your First System-Specific Routine (Clearing the Screen)
A common first task is to clear the entire screen buffer, filling it with a blank value (usually 20H
for a space character or 00H
for a black pixel/tile).
The Goal: Write the ‘blank’ byte (e.g., 00H
) to the 6144 bytes of screen memory, starting at 4000H
.
Routine using LDIR: This uses the fast block transfer instruction:
CLEAR_SCREEN:
LD HL, FILL_BYTE ; HL = Address of the byte we want to fill with
LD DE, 4000H ; DE = Start address of screen memory
LD BC, 6144 ; BC = Number of bytes to clear
LDIR ; Copy the single byte repeatedly
RET
FILL_BYTE:
DB 00H ; The byte we want to write (e.g., black or space)