Subscribe to RSS feed

My first, faltering steps in 6502 land

So me and a couple of friends decided to start a C64 demo group, just for fun. Now, I've coded a bit of assembly before, but never for the 6502 and certainly not for the video and sound chips in the C64 so this is new ground for me. Some other friends were interested too and requested that I blog about my experience trying to learn C64 assembly so I though, why not. So now that you know my reason for doing this, as if anyone needs a reason to play with C64 assembly, let's get started!

Getting the tools

To get started I had to get a few things:

  • An emulator
  • A cross assembler
  • A hello world


Since I'm running Linux, Vice seemed to be a logical choice. It is widely available and I just installed it through my distro, gentoo. I'll be using the x64 program here, which is the X-version of Vice.

When it comes to assembler, I was recommended DASM. It wasn't available in my distro of choice, so I downloaded and compiled it myself, which was straight forward.

As for a hello world, I found a nice intro on YouTube, but it wasn't a perfect fit for me since it showed a assembler running on the C64, which also has a slightly different syntax than DASM. So I did my best to adapt it and with a bit of help from a friend I got it to run!

There's also a problem of encoding the ASCII string into the code used by the character ROM. E.g., 'A' in the character ROM is 1, not 65 as in ASCII. I went full out and created a translation table from ASCII to ROM codes for all the characters on the C64. Another option would have been to just write the message string in ROM code directly, but it just looks so incomprehensible =)

6502 Assembly Basics

First of all, the 6502 has three registers we'll be using, the x, y and a registers. The a register is known as the accumulator, most arithmetic and logic operations use this both as one of the operands and to store the result. The x and y are general purpose registers that are slightly different to one another in how they can be used in some addressing modes.

The 6502 processor has a few different addressing modes and we use two of them here:

  • Immediate - The operand is given as a hard coded number.
  • Absolute indexed with x/y - A 16 bit address is given as a hard coded number and using x or y as an index.


Immediate operand is used to load an arbitrary number into a register and is done by preceding the operand with a hash sign.
; Load 0 into the a register.
lda #0

Absolute addressing indexed with x or y uses a fixed address, given as a number (or in my case as labels or constants) and then x or y. The operand is the byte that is located at the fixed memory address plus what is in the
given register.

; Load the code for the 'A' character into screen memory plus 3.
lda #1 ; Code for 'A'
ldy #3
sta $0400,y


Another keyword I'm using quite a bit is "dc.b", which simply tells the assembler to declare bytes of memory in that location. This lets you put data into the program and you can use it to create global variables. After a declare statement you can write a comma separated list of strings, numbers etc.

; Declare an ASCII string and terminate it with a 0-byte.
dc.b "HEJ", $00


Another version is "ds.b" which lets you specify how many bytes that you want and then what value should be stored in them.

; Declare 5 bytes all initialized to 0.
ds.b $05, $00


That should really explain most parts of the code, so let's get to the listing!

; Set up target processor and address where we wish to be loaded.
; Apparently these _have_ to be indented at least one step, otherwise
; DASM throws a fit.
	processor	6502
	org		$1000

; Address to start of screen memory.
SCREEN	equ	$0400

	;
	; Main code
	;

	; Use x as an index for how far into the string we are.
	ldx	#0
output_loop:
	; Load the next ASCII character into y.
	ldy	hello,x
	; If this is a NULL byte, quit looping.
	beq	end_output_loop
	; Load the ROM code for this ASCII character into a.
	lda ascii_to_rom,y
	; Store the code into screen memory.
	sta SCREEN,x
	; Increase x by 1.
	inx
	; And always jump back.
	jmp	output_loop

end_output_loop:
	; Exit the program.
	rts


; Null terminated hello world string in ASCII.
hello:
	dc.b	"HELLO WORLD!", $00

; Translation table from ASCII to C64 ROM codes.
ascii_to_rom:
        ds.b $20, $20
        dc.b " !",'","#$%&'()*+,-./"
        dc.b "0123456789:;<=>?"
        dc.b $00
; Use DASM macros to insert the numbers 1-26.
X       SET 1
        REPEAT 26
        dc.b X
X       SET X + 1
        REPEND
        dc.b $1b,$20,$1d


Assembling and Running the Program

Now, assuming we've saved the source code in the file hello.s, let's go ahead and assemble it into a prg-file that can be understood by Vice.

$ dasm hello.s -ohello.prg


And finally, let's get it running. To load the prg-file you can either start x64 with the prg-file as a command line argument, or if you want to have Vice running and reload the prg-file, you can use "Smart-attach disk/tape..." under the File menu and choose your file.

$ x64 hello.prg &


Now it's loaded into the C64's memory at the address given by the org-keyword in the source. Now we just have to tell the C64 OS to jump to that address, which is done by the SYS-keyword. We need to give it as a decimal number and since we set the address to $1000 (i.e., 1000 in hexadecimal) we need to run the following in Vice:

sys 4096


That's it! You should see "HELLO WORLD!" at the top left of the screen. Next time I'll be looking a bit at more advanced addressing modes, so that we can loop over larger data sets than 256 bytes and make some subroutines etc.

Oh, and I made this silly little scroller as an extension to the hello world program, go check it out!

References
6502 Assembly
DASM documentation

Random nerdery

Or how I abandoned newfangled GUI-gadgetry and learned to love the screen wink

Read more...

The great Oslo project!

Hello everyone. As you might have noticed, my blog on MyOpera has been pretty much dead quiet for the past year. I guess I don't feel that I have too much to write about, except for when I travel of course. Lately I've been thinking that it might be nice to perhaps put a bit more stuff on my page though.

I guess my nerdy glee over the nixie clock project woke up the creative spirit in me. If you haven't checked it out yet, be sure to do. Even though it's just 4 pics yet, there are lots of exposed electronics and cyrillic writing to be had! =)

Anyway, I've left my usual dwelling in Linköping to go work in Oslo for a while (don't worry, it's just a limited time project). Almost two weeks have passed since I left for Norway and I guess you could argue that not much has happened. Pretty much all I've done during the weeks is work and read books. But it's been quite interesting. The project I'm on right now is pretty secretive, so I can't say much about it, but it's quite fun (and seriously hard work).

I've also found time to see a bit of the night life and found out that Opera employees actually have discounts in several restaurants and bars around the office in Oslo. Now why don't we have that in Linköping? Maybe a bit of
lobbying is in order here wink

I'm housed in one of Opera's apartments during my stay here, sharing it with an Italian guy called Luca. Nice enough guy if you ask me. He's quite new here at opera and used to work at Ferrari in Italy (how's that for cool, eh?).

There's not much to do in the apartment, since my room is hardly big enough to turn around in (see the pic) and the living room has a small couch and a TV and oh yeah, a kitchen as well. Rune, one of the guys I'm working with, whom I've met a couple of times before in my work, was actually nice enough to lend me an old laptop. See what nice people you meet when you work at opera? It's actually the computer I'm writing on right now, even! Kind of interesting to be typing in English on a German keyboard with a Swedish layout, but what the hey, it works =)

Right now I'm getting really tired, I'm even at the point of being a bit lightheaded, so I'd better start wrapping up this post. Hopefully I'll do a bit more writing in the weekend, if I can come up with anything interesting to write about. Tomorrow it seems I'll be hitting the pubs with a few Linköpingites after work, but hopefully I will get home before eight in the morning this time (last Saturday was a blast though, thanks Aneesh =).

Keep checking my page though, I'll try to update it a bit more often. I do miss home and all of you in Linköping a lot. See you all in a couple of weeks!

/Abbe

Perspectives on a trek to change your life

Ok, I admit the title might sound (more than) a bit pretentious. It probably won't change my life, so much as nudge it a little bit.

Read more...

Back to civilization

After four days of walking, without access to gprs, we've started our bus trip back to Marrakech. On the way we've stopped for a nice lunch of tajin at a local food place. It seems full of trinket peddlers, much unlike the berber villages we've grown fond of during our trek.
At least we get to practice saying no in arabic.

A roof over our heads

After a few hours of walking we set up camp by a berber village, perched death defyingly on the side of a hill top. Better not do any sleep walking tonight...

Ain't on mountain high enough

After half a day of walking our cooks made a wonderful salad and we had our first outdoor meal. Already we've risen quite high above the plains, as you can see.

Snack time

We found the nicest guy, he even gave our guide a cassette of recited koran verses to enjoy at home.

A room with a view

We finally arrived at the hotel in Marrakech, just in time to see the sun set.

Brussels airport

The locals look a bit stiff. Maybe they soften up after a Leffe or two.