Lab 2 – 6502 Assembly Language(Not finished yet)

In Lab 2, We learned Assembly language base on 6502.

Here is the code:

lda #$00	; set a pointer at $40 to point to $0200
	sta $40
	lda #$02
	sta $41

	lda #$07	; colour

	ldy #$00	; set index to 0

loop:	sta ($40),y	; set pixel

	iny		; increment index
	bne loop	; continue until done the page

	inc $41		; increment the page
	ldx $41		; get the page
	cpx #$06	; compare with 6
	bne loop	; continue until done all pages


After we run the code above on 6502 Emulator, the screen will be filled by yellow.

Now we add tya between “loop” and “sta ($40), y” the screen will be filled by different color lines. The reason why it happens is that we write the data in register A to the screen pixels. Before we add tya, the data in a is #$07(yellow). But after we added tya, the data in register A will be changed in every loop from 00 to ff, the screen only take the last digit of the hex code as color code, so it only shows 16 color(0 – f). The screen size is 32*32(1024 pixels) and the screen contains 4 pages, from 0x200 until 0x50FF. so every page contains 256 (16*16) pixels and controls 8 (256 = 8*32) horizontal lines on the screen. Therefore, 16 colors pixels circle(0 – f) shows twice in a line cause a line has 32 pixels.

Now, let’s add lsr after tya. lsr shifts bit right for the data in register A, where saving the data that will be write to the screen. What gonna happen?

Well, it divides the unsigned integer stored in register A(we shift right once so that the integer is divided by 2^1). In this case, after we go through a line, the 16 colors circle only shows once and every color is showed twice.

Output when we shift bit right once

What if we add lsr once again?

We can predict that the color code will be divided by 4(2^2). In this case, we need 64 (loop 64 times, 16 = 64/4) pixels to show a 16 color circle and every color will be shown 4 times. We believe the vertical line will be break cause the number for pixels in each line cannot be divided by loop times of a circle of showing all colors.

shift right twice, lines break

What if we delete all lsr and write an asl between loop and sta ($40), y?

In this case, we can make sure that the last digit of data in register A will not be an odd number because the data in register A is multiple by 2.

we can see the last digit will be 0, 2, 4, 6, 8 ,A, C, E, 0…

There are only 8 colors in a color circle!

Also when we shift again, the number of colors reduces by half. Until there will only be 0 at the last of the color data, the screen will only show black


result of shift left 3 times, only 2 colors left.

Now we play around with register A, what if you do something to register Y, what will be the result?

Let’s clear all tya and asls, and add an extra iny.

In this case, our program will not go through the whole screen, it will actually go through half of the screen because the y will never be an odd number before it reach 00 – end of the loop. So, if there are 4 iny, the program will only render one fourth of the screen.

result of we having 4 inys

What if we have 3 inys?

This will be an interesting questions. For 3 inys, the program will render 0, 3, 6, 9, C, F for the first circle. What’s next? the data got overflow, so F+3 will be 2!

Then its rendering, 2, 5, 8, B, E then overflow again, E+3 is 1 and start loop again: 1, 4, 7, A, D. After we add 3 again, the data will be 0, loop end. so that can say that if we increase y odd times, it will finally render the whole screen – just slower!

write 1

Writes 1 – lines on the top and bottom:

;write 1 line on top and bottom.	
    
    
    lda #$00	; set a pointer at $40 to point to $0200
	sta $40	; I still don't know why it is pointed to $0200, needing answer
	lda #$02
	sta $41

	lda #$05	; colour

	ldy #$00	; set index to 0

loop:	
	sta ($40),y	; set pixel
	iny		; increment index
	cpy #$20	; compare index, 20 - end of first line
	bne loop	; continue until done the page
	lda #$00	; fill black to other pixels
	inc $41		; increment the page
	ldx $41		; get the page
	cpx #$05	; if last page of the screen - last 1/4
	bne loop

loop2:
	;sta ($40),y ; this line is not needed
	iny ; increase index
	cpy #$E0 ; compare index, E0, last line of the page
	bne loop2
	lda #$05 ; set green color
loop3: 
	sta ($40),y ; set pixels
	iny
	bne loop3

In this approach, we render the first line of screen: 0x0200 – 0x022F, first 32 pixels in first page.

Then we will ignore all other pixels of the page until we got 0x05E0, the last line of the screen, last 32 pixels in last page. then we render it, we got lines on the top and bottom

Write 2 – lines on the left and right:

; write 2 line left and right

	lda #$00	; set a pointer at $40 to point to $0200
	sta $40
	lda #$02
	sta $41
	lda #$00
	sta $42 ;counter to 0

	lda #$07	; colour yellow
	ldy #$00	; set index to 0
	sta ($40),y
loop:	
	iny		; increment index
	inc $42; ; increment counter
	ldx $42; load the counter
	cpx #$1F;  check if the counter 1F(32) - it is the last pixel of the line.
	bne loop; if no, loop until get the last pixel of the line. 
	lda #$04; color purple
	sta ($40), y ;set pixels
	iny ;increment index
	lda #$07; 
	sta ($40), y ;we got the first pixel of next line, or the first pixel of the page.
	ldx #$00; reset counter
	stx $42; store the counter back
	cpy #$00; 
	bne loop;loop until done of the page.

	inc $41		; increment the page
	ldx $41		; get the page
	cpx #$06	; compare with 6
	bne loop	; continue until done all pages
write 2 result

If we want to render the line on the left and right, we can render the first pixel and the last pixel of every line. We know that every line has 32 pixels, so we need a counter to know if we are in the the last pixel of a line – next pixel must be the first pixel of next line!

But there is an issue, when the program reach the last of a page, it cannot get the first pixel of next page because the address is pointed by the pointer! However, our program still rendered 2 lines as expected. Why?

After we reached the last pixel of a page, we need try to get the first pixel of next line and the machine does give our program a pixel – but it is the first pixel of current page instead of the first pixel of next line!

My impression of the Assembly Language:

It scared me when I first time heard about it. But actually when I am doing it, it is not hard as I thought. It is actually let the programmer program a machine step by step in a lower level. We have more control of memory so that we can write a high performance program.

I played a game call Human Resources Machine, which is very similar with writing in Assembly Language.

The loop, if, switch statements in higher level language like C/C++ are actually implemented by Jump function in Assembly!

(To be continued)

Leave a comment

Design a site like this with WordPress.com
Get started