Retro Computing – Writing ‘Hello World’ in BBC Micro 6502 Assembly Language

I anticipate writing occasional posts about BBC Micro machine code as I do harbour a fascination with this from all those years back as a 12 year old. Let’s start with something basic (or rather machine code, ho ho).

I think I probably speak for everyone when I say my first introduction to BASIC was writing something along the lines of:

10 PRINT "Simon Rules!"
20 GOTO 10

…to be greeted with my message endlessly scrolling down the screen. Happy days. It makes sense then to create the same in assembly language as an introduction then, surely? 🙂

In the traditions of this site, I will try keep it concise and to the point but as you can see below, in ASM you really have to tell the machine exactly what you need it to do – no simple instructions to simply write what you choose. Don’t worry though, explanations will follow. Here is the exact equivalent in ASM of what we just did above in BASIC:

20 P%=&2000
30 [
35.helloworld
36 EQUS "Hello World!"
37 EQUB &A
38 EQUB &D
40.print
50 LDX #0
60.loop
70 LDA helloworld,X
80 JSR &FFEE
90 INX
100 CMP #&D
110 BNE loop
115 LDX #0
116 JMP loop
120 RTS
130]
140CALL print

EXPLANATION

Line 20: P% represents the place in memory where the program will be run from and refers to the ‘stack pointer’. This is a built in variable and we will be running the program from &2000 in this case. Note: ‘&’ is used to denote hexadecimal notation will follow – many other machines at the time (and to this day for that matter) use the ‘$’ for this.

Line 30 and 130: All assembly code on the Beeb needs to be encased in square brackets.

Line 35: .helloworld marks the start of the function we use to define our output.

Line 36: On the BBC Micro, EQUS stands for Equate String and essentially reserves a piece of memory containing the string specified.

Line 37: On the BBC Micro EQUB stands for Equate Byte and essentially reserves a piece of memory containing the byte specified. So what’s &A ? This translates to decimal ’10’ and is the ASCII for the newline character. This will be processed after ‘Hello World!’

Line 38: As above but what’s &D ? This translates to decimal ’13’ and is the ASCII for the Carriage Return character. This will be processed after newline above and these two additions ensure anything printed subsequently is on a new line.

Line 40: .print marks the start of the routine we use to loop through and print our output.

Line 50: This loads the X register with zero. In practice, this marks the start of a loop, like a FOR loop at character 0 “H” in ‘Hello World!’

Line 60: .loop – marks the start of the loop we will use to cycle through the ‘Hello World!’ string we defines from line 36.

Line 70: Loads the accumulator by referencing the helloworld function at line 34. The X reference is keeping tack of where we are in the loop as we’re displaying the characters one by one (starting at 0 as mentioned in line 50).

Line 80: JSR stands for ‘Jump to SubRoutine’ and is used to jump to an in-built machine code routine to OSWRCH (Operating System Write Character). This is used, as you might imagine, to write characters to the screen and is found on the BBC Micro at &FFEE.

Line 90: INX is ‘Increment X register’ and increments this by one on each pass. This is part of our loop which is printing each of the characters in the string .

Line 100: CMP stands for ‘Compare’ and we are comparing the character we are on in the string with that here. ‘&D’ is decimal 13 and equates to the CR we mentioned in line 38. Since this is the last ASCII ‘character’ to be printed we know that if this is found, the full string has now been displayed.

Line 110: BNE stands for Branch if Not Equal and will continue the loop if &D hasn’t been found, above.

Line 115: Reset the X register back to 0. We need to do this as we will be re-running the whole code again in an endless loop and need to reset to the start of the string.

Line 116: Jump back into the loop. This is effectively ‘GOTO 10’ in the above BASIC version.

Line 120: Return From Subroutine (RTS) because &D has been found by the Compare above and we’re happy that the string we’ve printed is now complete. In practice, this is never reached as we are in a continuous loop but this is where it should go! If we were to remove lines 115 and 116 the program would complete here (and ‘Hello World!’ would be displayed once and finish).

Line 140: Finally we use the BASIC command CALL to execute the machine code routine to print the message.

That’s it…relatively straightforward although the BASIC equivalent is obviously somewhat easier to understand! I will hopefully do something a little more interesting next time, maybe draw a square on the screen or something. Let’s see.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.