SPO600 lab 1
Hi, my name is Daniel Park and this blog will contain information and notes on the SPO600 course I am taking. This class is about Software Portability and Optimization and I will be learning the use of Assembly Language for the first time.
The first part of this lab contains a piece of code which fills the display with yellow. We will determine various aspects of this code such as how long it takes to execute, the total memory usage, and ways to alter this for different output.
Below is the code:
lda #$00 ; set a pointer in memory location $40 to point to $0200
sta $40 ; ... low byte ($00) goes in address $40
lda #$02
sta $41 ; ... high byte ($02) goes into address $41
lda #$07 ; colour number
ldy #$00 ; set index to 0
loop: sta ($40),y ; set pixel colour at the address (pointer)+Y
iny ; increment index
bne loop ; continue until done the page (256 pixels)
inc $41 ; increment the page
ldx $41 ; get the current page number
cpx #$06 ; compare with 6
bne loop ; continue until done all pages
We are using a 6502 processor and calculating how long it would take to execute on a 1 MHz clock.
Using the 6502 instruction set we can see how many cycles each instruction takes. This website contains all the information I used to find how many cycles each instruction would take: https://www.masswerk.at/6502/6502_instruction_set.html
The code consists of two loops, one that fills out one page (256 locations on a page) and an outer loop which increments the page number and checks that it is less than 6.
Each inner loop will take 10 cycles each, then this is looped until it is 256. 10 x 255 = 2550 cycles for this loop. Then when it reaches 256 it will take 3 cycles rather than 3, so adding the loop one more time would result in 11 cycles plus the 2550 cycles we already have. In total one inner loop will take 2561 cycles.
The outer loop increments the page and retrieves the current page number and makes sure the number is less than 6. This will make the loop execute from $02 to $05, so 4 times total because after 5 it will exit the loop. When the branch is taken for the first 3 loops it will be 12 cycles and then 13 if the branch is taken on the final loop. So total outer loop time would be 49 cycles.
Now to add this all up as the loop will repeat 5 times, we can do 2561 x 5 = 12805 then we add the outer loop times for a total of 12854 cycles. Converting this to seconds is easy with 1 MHz clock which means 1 cycle = 1 micro second. Thus 12 854 cycles = 12.854 milliseconds to write the 5 pages.
The calculation of total memory usage was very simple and I just referred to the above website for the byte size of each instruction. most of the instructions were 2 bytes excluding incrementation which was 1. So, in total we have 27 bytes of memory being used throughout the whole program.
To modify this code we can reduce the times the code loops/iterates by using multiple STA operations in a single loop. Currently our code writes 1 pixel at a time however, if we add more sta operations and increment we can choose to have 4, 8, 16, etc... pixels. The idea is to write more blocks of memory for every loop so it needs to loop less. I will do 4 pixels for space/demonstration here.
sta ($40),y
iny
sta ($40),y
iny
sta ($40),y
iny
sta ($40),y
iny
bne loop
This will greatly reduce the execution time of the inner loop which takes the longest to execute. With rough math, its around 34 cycles per inner loop iteration, then 256/4 for 64 total iterations. 64 x 34 = 2176 cycles and this multiplied by 5 results in 10 945 cycles, reducing execution time by around 2 milliseconds. We can take this concept further and block these loops in even larger groups, thus reducing computing time greatly. Would just writing this all in one massive non loop be technically faster to execute?
Modifying code for various colours:
Changing the output colour to blue was as simple as changing the lda #$07 to lda #$06.
Altering the pages was a little bit more difficult but pretty straight forward.
lda #$00 ;
sta $40 ;
lda #$02 ;
sta $41 ;
ldy #$00 ;
loop:
ldx $41 ;
cpx #$02 ;
beq blue
cpx #$03 ;
beq green
cpx #$04 ;
beq red
cpx #$05 ;
beq yellow
lda #$08 ;
jmp page_fill
blue:
lda #$06 ;
jmp page_fill
green:
lda #$05 ;
jmp page_fill
red:
lda #$02 ;
jmp page_fill
yellow:
lda #$07 ;
page_fill:
sta ($40),y ;
iny ;
bne page_fill ;
inc $41 ;
cpx #$06;
bne loop ;
This lab was very straight forward for me and I have a lot of fun playing around with assembly language. Writing in assembly really makes me think like a programmer, and be very concise and clear with my instructions. Although this can be frustrating its also rather straight forward when coding basic things such as this. It's still crazy to me how we came from this level of computing to modern day languages.
Comments
Post a Comment