# Advanced Memory Segments

By now we've covered the basics of every command in the assembler; in this final installment we show the full capabilities of the `.text` and `.data` commands as we produce a more sophisticated set of Commodore 64 header files.

## The Problem

Our `print'str` routine in tutor6-fname accesses memory locations $10 and $11 directly. We'd prefer to have symbolic names for them. This reprises our concerns back in ch5-link when we concluded that we wanted two separate program counters. Now we realize that we really need three; one for the text, one for the data, and one for the zero page data. And if we're going to allow three, we really should allow any number.

## The Solution

The `.data` and `.text` commands can take a label name after them—this names a new segment. We'll define a new segment called `zp` (for zero page) and have our zero-page variables be placed there. We can't actually use the default origin of $0000 here either, though, because the Commodore 64 reserves memory locations 0 and 1 to control its memory mappers:

    .data zp
    .org $0002

Now, actually, the rest of the zero page is reserved too: locations $02-$8F are used by the BASIC interpreter, and locations $90-$FF are used by the KERNAL. We don't need the BASIC interpreter, though, so we can back up all of $02-$8F at the start of our program and restore it all when we're done.

In fact, since we're disablng BASIC, we can actually also swap out its ROM entirely and get a contiguous block of RAM from $0002 to $CFFF:

    .scope
            ; Cache BASIC zero page at top of available RAM
            ldx     #$8e
    *       lda     $01, x
            sta     $cf81, x
            dex
            bne     -

            ; Swap out the BASIC ROM for RAM
            lda     $01
            and     #$fe
            ora     #$06
            sta     $01

            ; Run the real program
            jsr     _main

            ; Restore BASIC ROM
            lda     $01
            ora     #$07
            sta     $01

            ; Restore BASIC zero page
            ldx     #$8e
    *       lda     $cf81, x
            sta     $01, x
            dex
            bne     -

            ; Back to BASIC
            rts

    _main:
            ; _main points at the start of the real program,
            ; which is actually outside of this scope
    .scend

Our `print'str` routine is then rewritten to declare and use a zero-page variable, like so:

    ; PRINTSTR routine.  Accumulator stores the low byte of the address,
    ; X register stores the high byte.  Destroys the values of $10 and
    ; $11.

    .scope
    .data zp
    .space _ptr 2
    .text
    printstr:
            sta _ptr
            stx _ptr+1
            ldy #$00
    _lp:    lda (_ptr),y
            beq _done
            jsr chrout
            iny
            bne _lp
    _done:  rts
    .scend

Also, we ought to put in an extra check to make sure our zero-page allocations don't overflow, either:

    .data zp
    .checkpc $90

The final source file is tutor7-fname.