Page 1 of 1

64Tass Structural Programming Macros

Posted: Thu Nov 27, 2025 11:50 pm
by laztrezort
Hello, new here so apologies if this has been done before and posted...

I've just started learning to use the 64Tass assembler (and brushing up on assembly language in general), and I was inspired by the wonderful article here https://wilsonminesco.com/StructureMacros/ to port some of these macros over to tass. This process has certainly helped me understand the features of Tass - I've tried to utilize the more advanced macro features where I could when porting (lists, slices, nested macros, etc.)

Posting here in case anyone finds use for these. Included a tiny bit of test/example code as well.

At some point I'll likely do more testing, as well as maybe add some more macros (for..next for sure). But I really should get back to the original point of me learning all this, and finish my emulator...

Caveat: These are all largely untested, and as I said above I'm certainly no pro at assembly nor 64Tass, so I'm sure there bugs somewhere in there.

Re: 64Tass Structural Programming Macros

Posted: Fri Nov 28, 2025 12:26 am
by GARTHWILSON
It's nice to see others picking up on this and doing it for other assemblers!  The program flow control structure macros have sure increased my productivity in, and enjoyment of, assembly language.

Re: 64Tass Structural Programming Macros

Posted: Fri Nov 28, 2025 3:59 am
by BigDumbDinosaur
laztrezort wrote:
Hello, new here so apologies if this has been done before and posted...

I've just started learning to use the 64Tass assembler (and brushing up on assembly language in general), and I was inspired by the wonderful article here https://wilsonminesco.com/StructureMacros/ to port some of these macros over to tass.

I’m a big user of macros, to the point, in fact, where most of the mainline code in some of my programs is a series of macro invocations, with a few “raw” assembly language statements in places where macros don’t help any.  As I do a lot of development for the 65C816, there tends to be a lot of activity involving stack frames and direct-page relocation, areas in which some truly awesome bugs can be created in one’s code.  :shock:  For that reason, many of the macros I have written cater to “automating” such tasks (see attached for an example).  In that respect, properly designed macros can do a lot to extend the life of the system’s reset push button.  :D

However, I’ve never gotten into using macros to imitate high-level constructs, as Garth has done.

pushparm.asm
Stack Frame Generator Macro
(5.22 KiB) Downloaded 45 times

Re: 64Tass Structural Programming Macros

Posted: Fri Nov 28, 2025 5:29 am
by laztrezort
GARTHWILSON wrote:
It's nice to see others picking up on this and doing it for other assemblers!
Appreciate you creating that article (along with all the others)! Very helpful stuff.
BigDumbDinosaur wrote:
For that reason, many of the macros I have written cater to “automating” such tasks (see attached for an example)
Thanks for sharing some more for me to chew on! I'm not too familiar with the '816 yet, but generally my path forward is to get a 65c02 emulator working, then transition the code to an '816 emulator, so sooner or later I'll be digging through those manuals and materials.

Re: 64Tass Structural Programming Macros

Posted: Fri Nov 28, 2025 7:12 pm
by soci
Hello laztrezort!

I'd recommend an alternate approach by stacking namespaces instead of branch instruction locations.

The advantage is that it's possible to define symbols like _skip or _loop in them. Using these as branch destinations there's no need for patching with .byte directives. Error diagnostics will work better, it's compatible with automatic long branching and the assembly listing becomes more readable.
StructuralMacros2.asm
Same, with namespaces
(4.8 KiB) Downloaded 57 times

Re: 64Tass Structural Programming Macros

Posted: Fri Nov 28, 2025 8:24 pm
by GARTHWILSON
soci, is that .asm code for the 64Tass assembler?  It'd be good if you could add some comments of explanation for those of us not familiar with that assembler.  I am unfamiliar with most of those assembler directives (at least I guess that's what they are, starting with a dot).

An advantage of the structure macros is that you don't need symbols like _skip or _loop.  The names of the macros, invoked in the code using them, plus indentation to set off nested structures, makes it clear what's going on.  You can still of course use labels, like if you had some odd reason to jump into the middle of a structure.  The structure macros just add a nice tool, without adding any constraints.

Re: 64Tass Structural Programming Macros

Posted: Sat Nov 29, 2025 12:53 am
by laztrezort
soci wrote:
I'd recommend an alternate approach by stacking namespaces instead of branch instruction locations.
Wow, that's amazing, I had no idea one could (ab)use namespaces like that! Also, I see I was using naive list handling in my code - thanks for sharing.
GARTHWILSON wrote:
An advantage of the structure macros is that you don't need symbols like _skip or _loop.
I'm still trying to wrap my ahead around it a little, but I believe it's basically just using those symbols as temporaries to get the assembler to do the branch target patching, instead of manually filling in the branch opcodes. The 64Tass scoping hides all of those symbols so you're not polluting your normal symbol namespace, and aren't meant to ever be used directly.

Re: 64Tass Structural Programming Macros

Posted: Sat Nov 29, 2025 2:47 am
by GARTHWILSON
laztrezort wrote:
GARTHWILSON wrote:
An advantage of the structure macros is that you don't need symbols like _skip or _loop.
I'm still trying to wrap my ahead around it a little, but I believe it's basically just using those symbols as temporaries to get the assembler to do the branch target patching, instead of manually filling in the branch opcodes. The 64Tass scoping hides all of those symbols so you're not polluting your normal symbol namespace, and aren't meant to ever be used directly.
I'm kind of lost since I'm not familiar with 64Tass; but once the macros are written and proven, there's no further reason to look at their innards (except maybe when you want to use them as templates to modify to make new macros).  Then it doesn't matter how they do their job silently behind the veil, although you're keeping in mind that (in most cases) they're assembling exactly the same thing you would by do hand if you didn't have the luxury of the macros.

Re: 64Tass Structural Programming Macros

Posted: Sun Nov 30, 2025 8:56 pm
by soci
GARTHWILSON wrote:
soci, is that .asm code for the 64Tass assembler?  It'd be good if you could add some comments of explanation for those of us not familiar with that assembler.  I am unfamiliar with most of those assembler directives (at least I guess that's what they are, starting with a dot).
Yes, those are 64tass directives. I haven't explained them as they're a documented elsewhere and thought there isn't much interest.

The .namespace/.endnamespace pair creates or uses a namespace. This allows sharing symbols across "#if" and "#else" or "#endif" for example.

The .segment/.endsegment directives are the non-scoped versions of .macro/.endmacro. I've used them because scoping would be redundant due to .namespace/.endnamespace and also if no labels are defined which need hiding.

The .function/.endfunction directives are used to implement namespace stack push/pop operations. A new empty one is added to the end (-1) or gets sliced off. Both return the top of the stack as that's what's needed to select the namespace where new labels will be defined or where the label for the branch resides.

That .switch/.case/.default/.endswitch block is a shorthand for .if/.elsif/.else/.endif and .proff/.pron hides code in listing.

Re: 64Tass Structural Programming Macros

Posted: Sun Nov 30, 2025 9:41 pm
by BigDumbDinosaur
soci wrote:
That .switch/.case/.default/.endswitch block is a shorthand for .if/.elsif/.else/.endif...

Pardon me for being a gruff curmudgeon, that’s too much complication in an assembler, in my opinion.

Programming in assembly language means one is working in an inherently low-level environment that is fundamentally simple in nature.  Adding pseudo-ops in an effort to make the assembler appear to be higher level doesn’t make for a better assembler, just a more complicated one.

If the purpose of adding all that .CASE .SWITCH mumbo-jumbo is to mask the low-level nature of assembly language, why not just program in a higher-level language, e.g., C?  With a good compiler, C programs will run plenty fast, though not as fast as pure assembly language equivalents, but will spare the programmer from having to know about those nasty mnemonics and detailed hardware matters, such as the 65C816’s banking rules.

Re: 64Tass Structural Programming Macros

Posted: Sun Nov 30, 2025 11:04 pm
by gfoot
BigDumbDinosaur wrote:
soci wrote:
That .switch/.case/.default/.endswitch block is a shorthand for .if/.elsif/.else/.endif...

Pardon me for being a gruff curmudgeon, that’s too much complication in an assembler, in my opinion.

Programming in assembly language means one is working in an inherently low-level environment that is fundamentally simple in nature.  Adding pseudo-ops in an effort to make the assembler appear to be higher level doesn’t make for a better assembler, just a more complicated one.

If the purpose of adding all that .CASE .SWITCH mumbo-jumbo is to mask the low-level nature of assembly language, why not just program in a higher-level language, e.g., C?  With a good compiler, C programs will run plenty fast, though not as fast as pure assembly language equivalents, but will spare the programmer from having to know about those nasty mnemonics and detailed hardware matters, such as the 65C816’s banking rules.
They aren't pseudo-ops though, they are assembler directives that control the conditional assembly of the code - at least that's what I assumed. For example, your pushparm.asm would be a lot clearer if it could use switch and case directives to check .m against the various options, instead of nested (and increasingly indented) if/else directives. Ultimately these preprocessor-like constructs are all there to make it possible to write more powerful macros, enabling the user code to be conceptually simpler and less repetitive. Even though I don't personally use macros much, as I do like sticking more-or-less to the instructions that the processor understands natively, I do see the value in them.