Understanding 6502 assembly on the Commodore 64 - (15) The Zero Page

Many people learning 6502 will often hear about the mystical and revered Zero Page area of memory, and all of the magical things it can do.  Well, there is no trickery behind it. The concept is actually quite easy to understand. We can get through this in a single post.









Consider for a minute how we have been addressing ourselves with regard to memory and what is happening within the inner workings of the processor.

lda #$55      -     A9    55
sta $0C00     -     8D    00    0C



On the first line A9 our LDA loads the hex value 55 in the Accumulator.  This required 2 cycles to be accomplished.

On the second line 8D stores the value in the Accumulator to 0C00    00 0C (little Endian). This required 4 cycles to be accomplished, as the actual storing of the data took a cycle


Our first line took 2 bytes, our second line took 3 bytes for a grand total of 5 bytes and 6 cycles.  I know this is obvious, but bear with me a moment.

The zero page memory area is basically $0000 - $00FF, conceptually it is no different than any other area of memory.  What makes zero page particularly interesting is how the 6502 processor can deal with it.  The 6502 allows us to express the addresses within zero page as one byte, leaving off the 00 MSB from the memory address.  Lets look at out initial example in zero page.  For my small examples now and going forward I will be using 00FB through 00FE for demonstrations when I can.  This area of memory has been set aside on the C64 as unused and available for machine language programs.   Yes, thats right, 4 whole bytes.



lda #$55       -     A9    55
sta $FB        -     85    FB

A simple move to zero page, with no other optimizations reduced the code size from 5 bytes to 4.  The use of zero page reduced our cycles on the second line from 4 to 3.

This is a 20% reduction in code size and about a 17% reduction in processor cycles.  All of which was accomplished simply by using zero page as storage.

So, where did that 85 come from? When we use an assembler we simply type STA $FB, but when it is broken down into machine code, the assembler sees that we are using zero page and produces the OPCODE for it.  With 85, the processor is only expecting one byte to follow it, not 2, as with 8D

At best, zero page is only 256 bytes long.   Luckily on the C64,  and other computers, a lot of the zero page is used by BASIC.  If we can forego the use of basic, we end up with quite a bit of room available.  Consider a program that had many routines and loops requiring saving to particular memory addresses. how much would zero page save us.

Lets take our optimized binary converter in the last chapter



; C64 Hex to Binary display converter optimized
; 64TASS assembler style code for 6502
; Jordan Rubin 2014 http://technocoma.blogspot.com
;
; Takes the HEX value in OURHEXVAUE, converts it to Binary for display 
; on the screen as a binary number.   
   
*=$C000 ; SYS 49152 to begin

OURHEXVALUE = #$55 ; Enter the Hex value to be converted here

OURHEXNUM = $033C  ; This is where the constant OURHEXVALUE will be stored
TESTBYTE = $0345   ; This is where our test byte will be stored for lsr
BIT7 = $0708       ; This is the location of the 7th bit, required room for
               ; 8 contiguous bytes after the starting address
               ; using 0708 dumps it right to screen ram, bottom center

nop


INIT:

lda OURHEXVALUE ; this will be out test number 
sta OURHEXNUM   ; we will store the test number here permanently       
ldy #$80        ; Out first bit test for bit 7 must be 10000000 $80 
sty TESTBYTE    ; Store our initial test byte here
ldx #$00        ; Initialize X for our loop

CONVERTION:

lda OURHEXNUM   ; load our test hex number, this is a constant
and TESTBYTE    ; mask it with our test byte
cmp #$00        ; is the result 00?
bne STORE1      ; No, jsr to STORE1
lda #$30        ; Load the display value of 0 into A
jmp CONTINUE    ; jump to CONTINUE

STORE1:

lda #$31       ; Load the display value of 1 into A

CONTINUE:

sta BIT7,x     ; Load the display value into A
inx            ; Increment X for our loop
lda TESTBYTE   ; load testbyte into A                                                                                                                              
lsr            ; divide it by 2
sta TESTBYTE   ; store new testbyte back to its memory area
cpx #$08       ; is X=8?
bne CONVERTION ; No, LOOP back to CONVERSION
brk

OUR current code, as shown occupies memory area C000 to C02D. [46 bytes]

Executing it in virtual 6502 shows it required 319 Cycles to complete


ea a9 55 8d 3c 03 a0 80 8c 45 03 a2 00 ad 3c 03 2d 45 03 c9 00 d0 05 a9 30 4c 1e c0 a9 31 9d 08 07 e8 ad 45 03 4a 8d 45 03 e0 08 d0 e0 00




Now lets make a few changes to it right at the top..........

OURHEXVALUE = #$55 ; Enter the Hex value to be converted here
OURHEXNUM = $FB    ; This is where the constant OURHEXVALUE will be stored
TESTBYTE = $FC     ; This is where our test byte will be stored for lsr
BIT7 = $0708       ; This is the location of the 7th bit, required room for
               ; 8 contiguous bytes after the starting address
               ; using 0708 dumps it right to screen ram, bottom center


Now well recompile it...........
OUR new code, as shown occupies memory area C000 to C027. [40 bytes]
Executing it in virtual 6502 shows it required 285 Cycles to complete

ea a9 55 85 fb a0 80 84 fc a2 00 a5 fb 25 fc c9 00 d0 05 a9 30 4c 1a c0 a9 31 9d 08 07 e8 a5 fc 4a 85 fc e0 08 d0 e4 00





From 46 Bytes to 40 Bytes was a code size reduction of 13%
From 319 cycles to 285 cycles was a cycle reduction of over 10.5%


The bigger the program and the more references to memory, the greater the benefit of using zero page.


NEXT----->
Understanding 6502 assembly on the Commodore 64 - (16) Input and Data Manipulation

Table of contents

No comments:

Post a Comment