WLA-DX Operand Size And Zero Page Bug Fixes

by ADMIN 44 views
Iklan Headers

Hey guys, let's dive into a pretty interesting issue I stumbled upon while using WLA-DX, a fantastic assembler, for some 6502-based CPU projects, specifically the HuC6280 variant. I was wrestling with operand sizes, something many of us encounter, and I think I might've found a little bug. Plus, I've got a suggestion for a new mnemonic that could make life a bit easier. This is all based on the master version of WLA-DX as of this writing.

The Operand Size Mnemonic Conundrum

So, the core of the problem lies in how WLA-DX handles operand size mnemonics, like .b for byte and .w (implicitly in .16bit mode) for word. It seems like there's a discrepancy in how the assembler interprets these when they're placed after the operand (the address) versus after the instruction itself. The general expectation, and what I'd argue is the more intuitive approach, is to place the size mnemonic after the operand. That's where you're telling the assembler, "Hey, I want this memory location, or this value, to be treated as a specific size."

Let's look at a small code snippet to illustrate this. In this context, we are using .16bit mode, which generally assumes 16-bit addressing, meaning addresses are 2 bytes long:

.16bit

sta $50    ; This should store the accumulator in the 16-bit address $0050.
sta $50.b  ; This should store the accumulator in the 8-bit address $50
sta.b $50  ; This should store the accumulator in the 8-bit address $50

Now, here's what actually happens. When I assemble this, the results are a bit surprising: placing .b after the operand doesn't always give the expected behavior, while placing it after the instruction works as expected! According to the expectation, sta $50 should store the accumulator in the 16-bit address $0050, which is the correct way. Placing .b after the address, sta $50.b, should store the accumulator in the 8-bit address $50, but it also acts like the 16-bit address $0050! Finally, sta.b $50 stores the accumulator in the 8-bit address $50. This inconsistency makes it tough to write clean and readable code, especially when you're trying to be explicit about the operand sizes. It's counterintuitive because most of us would naturally expect the size modifier to stick with the operand it's modifying.

This isn't just a matter of aesthetics; it impacts the code's readability and maintainability. When the size mnemonic is placed near the operand, it's immediately clear what's going on. It makes the code easier to understand at a glance. But, when the behavior is inconsistent like this, you have to constantly double-check what's happening, which slows down the development process and makes it more prone to errors. This is especially critical when working with different addressing modes or memory maps where byte and word accesses have very different effects.

I know this might seem like a small thing, but in the grand scheme of things, it's these small details that make a big difference in the overall experience of working with an assembler. The more intuitive and predictable the behavior, the easier it is to build complex projects and the more fun you can have while doing it!

HuC6280 and Zero Page Woes

Now, let's get into another interesting point specific to the HuC6280. For those unfamiliar, the HuC6280 is a CPU found in the PC Engine (also known as the TurboGrafx-16). One key detail is the zero page's location, which begins at $2000 instead of the usual $0000. This difference can cause some headaches when you're working with symbols in .16bit mode.

When you try to use a symbol for a zero-page address, things get a bit tricky. In .16bit mode, WLA-DX typically assumes 16-bit addresses, which can lead to errors if you're not careful. Let's look at another code example to illustrate:

.16bit

; The PC Engine's zero page starts at $2000 :')
.ramsection "zp" slot 1 orga $2000 force
foo db
.ends

sta foo    ; Stores at $2000, as expected.
sta foo.b  ; Stores at $2000, as expected, but not ideal
sta.b foo  ; Error!
sta <foo   ; Still stores at $2000, but truncates the address to 8-bit
sta <foo.b ; Still stores at $2000, and truncates the address to 8-bit, but also not ideal
sta.b <foo ; Stores at $0000, which is probably not what we want.

In this example, we define a zero-page symbol foo located at $2000. When you use sta foo, it works, because it defaults to a 16-bit address and correctly stores the accumulator at $2000. However, when you start playing with .b or < to try to force an 8-bit access, it can get a bit confusing. Sometimes it throws an error, sometimes it doesn't, and sometimes the results are not what you expect. Specifically, the last line, sta.b <foo, will store the accumulator in $0000, which is probably not the intent, because it effectively truncates the address to an 8-bit value, and then uses the lower byte.

The < symbol is the