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:

  1. Program Load Address (ORG): Where our code starts.
  2. Screen Memory: The RAM address where display data is stored.
  3. 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)