Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
Hello,
As a hobby project (and a way to learn how it all comes together), I've been working on my own assembler for the Gameboy. I'll be diving into preprocessor/directive commands soon-ish and I'm hoping to get some ideas from those of you who are pretty well-versed in assembly programming.
Obviously, the most common things like DB, DW, ORG, INCLUDE, etc will be included. Plus code expansion stuff like REPT and MACRO support. But what other types of assembler/preprocessor directives would make your programming life easier? This could be anything from an existing assembler feature to something you've completely made up but have never seen implemented. The goal is to have a nice powerful assembler specifically geared towards the original Gameboy. Once it's in a solid working state, I will be open-sourcing it. I just want to make sure the base for future development is as good as possible first.
Thanks for your help!
Offline
Hi there!
There's one feature I really want in an assembler, and even briefly entertained the idea of writing an assembler myself just to implement it. It's a convenience feature that's meant to help programmers add visual structure within their subroutines. I call them braced code blocks.
Within a subroutine, you may write a pair of curly braces (I chose curly braces because I spend a ton of time with C-family languages, so they're what comes naturally to me), with indented instructions within.
mySubroutine: ; Some instructions { ; Some more instructions } ; Even more instructions ret
On their own, these braces do nothing. In fact, internally they're just special temporary labels (and labels themselves are also just an assembler-level convenience). When execution reaches an opening brace, execution simply enters the block. When execution reaches the closing brace, it exits the block. Effectively, it's the same as if the braces weren't even there.
The utility comes from two new quasi-instructions, `continue` and `break`. These instructions resolve to jump instructions. The `continue` instruction jumps to the opening brace. The `break` instruction jumps to the closing brace.
So the braced code block feature is really just syntactic sugar around vanilla labels and jumps. But they enable visually distinct common code structures.
For example, an if statement:
mySubroutine: ; Some instructions { ; break if [address] != 0 ld a, [address] cp a, 0 break nz ; Body of the `if` statement here } ; Even more instructions ret
A `while` loop is identical to an `if` statement, just with a `continue` at the end.
mySubroutine: ; Some instructions { ; break if [address] != 0 ld a, [address] cp a, 0 break nz ; Body of the `while` loop here ; Loop continue } ; Even more instructions ret
I think something like that would make my code look far more structured than a continuous run of labels and seemingly-arbitrary jump statements all over the place. And since it just resolves to labels and jump statements, it's just syntactic sugar for old-fashioned assembly.
Offline
That's a really interesting idea. Since the braces define the beginning and end of the loop, that final continue wouldn't be necessary, right?
You could essentially do something like this:
mySubroutine: ; Some instructions... { ; More instructions... .BREAK [condition code] ; jp/jr to } ; More instructions... .CONTINUE [condition code] ; jp/jr to { ; More instructions... { ; Nested loop! ; More instructions... .BREAK [condition code] } ; More instructions.. } ; No need for an additional .CONTINUE here - Automatically jp/jr to { ; Even more instructions... ret
I'll have to think about this one, but off the top of my head:
* Pass one will keep track of the addresses for each { and } and push them onto an internal stack (or two, loopStart and loopEnd). This will allow nested loops.
* Pass two will pop the values from the loop stacks and generate the jp/jr instructions.
We'll see how it works in practice when I get there. It could even go so far as having locally-scoped labels for even more program flow choices
This is a really nice idea. Thanks for the suggestion!
Offline
Well if you automatically jump to the top brace when you reach the end of the block you wouldn't need the `continue` instruction I inserted in my loop example, but you would need to add a `break` instruction at the end of the `if` example. I envisioned the feature as simply allowing code execution to pass through the end of a code block, no automatic looping, so you don't need anything at the end of an `if`, but do need a `continue` at the end of a loop. The braces are simply labels, and `break` and `continue` are simply aliases for jump instructions to the corresponding brace, there's no automatic insertion of jump instructions at the end of the block.
Last edited by DonaldHays (2016-08-12 21:21:23)
Offline
Ahh ok. Sorry, for some reason my mind decided to only zoom in on the loop section.
I read through your post again and I understand it now. The braces are simply for better visual organization.
The break and continue instructions are the jumps. Internally, the braces are labels/addresses that are only used by break and continue. It could still work the same way I described to allow nested blocks. Just without the auto-jump generation on a closing brace.
Am I on the right track now?
Offline
Yup, exactly!
Offline
Woo! K. Added to the list. Thanks!
Offline
Assembler level variables please.
Offline
Jesse wrote:
Assembler level variables please.
Can you give me a little more detail?
Do you mean re-assignable symbols? In-code assembler switches? Or something more like higher-level language variables with types (byte, word, string, char, etc)?
Thanks
Offline