Inside the Einstein: The MOS, a TatungBytes course: the MOS 1.2 start up screen on a rainbow sunburst
← Back to Modules
module
4

Two Memories at One Address

Introduction

S2 left a puzzle. The Z80 can address 64K. The Einstein has 64K of RAM and an 8K ROM. Something has to give.

Switching

The Einstein's designers put the ROM at the same addresses as the bottom of RAM and added a switch. Writing anything to port 24h flips the bottom 32K of the address space, 0000h-7FFFh, between the two:

  • ROM in: addresses 0000h-1FFFh read the MOS.
  • RAM in: the same addresses read RAM, like the rest.

The top half, 8000h-FFFFh, is always RAM. At power-on the ROM is in, which is how the MOS gets to run first (S3). When your program runs, RAM is in - it has to be, because your program is in that RAM, at 0100h.

So the same address holds two different bytes. Take 0145h. In the ROM it is the 2 of MOS 1.2 in the banner. In RAM, after start-up, it is FFh.

What it costs

A machine built like this pays for its extra RAM in three ways:

  1. A running program cannot see the ROM. A CALL to an address in the MOS would land in RAM, on whatever happens to be there.
  2. The switch is dangerous from below 8000h. The instant you switch, the bottom 32K changes under the processor's feet. Code running at 0100h would find itself running the ROM's bytes at 0100h instead. The code that flips the switch must sit in the top half.
  3. Anything that must always be reachable has to live in the top half - or be present in both the ROM and the RAM at the same address.

Keep the third point in mind. It is the key to how the MOS answers your RST 8 calls (S7), and the reason it copies part of itself into RAM at start-up (S6).

The code

This program reads 0145h twice: once directly, and once with the ROM switched in. It obeys rule 2 by copying the four instructions that switch up to 9000h and calling them there:

        ORG 256

        LD A,(0145h)    ; read 0145h as your program sees it
        RST 8
        DEFB 158        ; print it

        LD HL,PEEK      ; copy PEEK up to 9000h, above the switch
        LD DE,9000h
        LD BC,PEEKEND-PEEK
        LDIR
        DI              ; nothing else runs while the ROM is in
        CALL 9000h      ; A = the ROM's byte at 0145h
        EI
        RST 8
        DEFB 158        ; print it
        RET

PEEK:   OUT (24h),A     ; bottom 32K: ROM
        LD A,(0145h)
        OUT (24h),A     ; bottom 32K: RAM again (A is not disturbed)
        RET
PEEKEND:

The value written to port 24h does not matter - any write flips the switch - so OUT (24h),A can be used without disturbing A. That is what lets PEEK carry the byte it read back across the second switch.

Build and run

Press Run.

What you should see

>█2
 A   BC   DE   HL   PC  SZ-H-PNC
32 0000 9008 0120 0FA5 00001000

The first character is a solid block: the character for FFh, the RAM's byte. The second is 2, the ROM's. The register display confirms it: A holds 32h, the code for 2.

Summary

Port 24h switches the bottom 32K between ROM and RAM. Your program runs with RAM in, so it cannot call into the ROM, and code that switches must run above 8000h. Anything the MOS needs reachable at all times must therefore be in high RAM, or at the same address in both memories.

Next

S5 gets you the tools to read the MOS for yourself: the source, how it is checked, and how to build and boot a ROM image of your own.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.