
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 where it was all complete gobbledegook to me. In all honesty it still is although I do at least have a (very) high level understanding of how it works these days. One of my new years resolutions was to improve that understanding so it seems appropriate to start with something basic (or rather machine code).
In the traditions of this site, I will keep it as concise and to the point as I can although some explanations will be necessary. Let’s start with the code:
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
120 RTS
130]
140CALL print
I will attempt to explain this line for line:
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 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.
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 arguably not as straightforward as 10 PRINT “Hello World!” š
Hopefully do something a little more interesting next time, maybe draw a square on the screen or something….I need to figure it out first though!