abrasax: (c64)
Continued from where I stopped this morning: adding the * 'variable' feature to my fork of the LADS assembler.

Ever since I created Txula, my fork as it were, I've toyed with this idea of the *, only to drop it. I didn't conceive of a way to implement it until today. I'm gonna do it, damn it.

The *, used for arguments like JMP *+6, is a quick and dirty way to establish a location for JMPs, JSRs, BXXs that wouldn't rely on labels OR knowledge of the program counter's value. That's because assemblers that use the * interpret it to mean 'the current value of the program counter at the start of the current line' - or, at least, that's how I interpret the *. Point of Order: in assembly / machine language programming, the code sits in RAM and runs on RAM directly on metal as they say. The program counter is a CPU register that keeps track of the RAM location or position (ie addresses) where the current line of code exists. In reality there are no labels; labels only exist for the programmer's convenience; it's just raw RAM addresses.

First, the hard part: settling on how to use the * with my fork.

It's to substitute for a label, yes? So how do work with labels? With Txula I use the / and the & as prefixes to indicate how a label is going to be used: the /'s are for positionals and the &'s are for arguments.

Example 1
/loopLDA &buffer,y
BEQ &quit
JSR &print
INY
BNE &loop
/quitRTS


Example 1 is a block of code that uses a do loop structure. The /loop and /quit are positional labels that establish via the program counter where the loop starts and ends. The &buffer, &quit, &print, and &loop are argument labels used as opcode arguments. In both cases the label's actual name is the text that follows the / and the & prefixes. Neither LADS nor Txula put a lot of restrictions on the sizes or the names of labels. Rather, we've got guidelines: don't use DATA and REM or words that contain them since the BASIC tokenizer goes wonky if you do; don't make them too big (or too small); don't use special characters the assembler recognizes as delimiters. But the / and the & prefixes are entirely my own novelty and what sets my fork apart. I conceptualize it as 'strong typing' even though that's utter nonsense given that it's assembly.

So I decided to keep my prefix framework intact. Using the *, the same code as above reads:

Example 2
LDA &buffer,y
BEQ &*+8
JSR &print
INY
BNE &*-9
/quitRTS


Cleaner(ish); note how that the &'s are still required.

Then I decided that having any label start with the * up-ends the assembler's normal way of dealing with labels altogether.

If a positional label starts with *, /* or /*loop or /*quit, then the assembler treats that as a decoration. It skips processing it as a positional label but keeps it strictly for screen or printer output (hence why it's a decoration at that point). Further, if an argument starts with *, &*+8, or &*quit+8, then the assembler treats that as just the * with extra letters for decoration.

Why the decorative treatment? In Example 2 I've got BEQ &*+8 and BNE &*-9, both are conditional branching opcodes, kinda/sorta IF/THEN/GOTO's, so if they're triggered by a condition, they branch to the location specified by their arguments. In both cases though it's just the * with offsets, of course, but the *'s don't give you a lot of clues about what you were meaning to do, does it?

What if you had:

Example 3
/*loopLDA &buffer,y
BEQ &*quit+8
JSR &print
INY
BNE &*loop-9
/*quitRTS


You'd say well that's just as dreadful as the first example, mate. Not gonna argue with that (pun intended hahaha) but this third example, like the second example, doesn't have labels at all. The /*loop and /*quit are treated as decorations since *loop and *quit start with the *. Likewise the &*quit and &*loop aren't labels but (decorated) calls to the current program counter value. Except now they give you a visual clue about where you intend them to branch to. Ultimately, the two advantages to this are: speed and conservation of RAM. Speed - because you don't have to look up labels from the database. Conservation of RAM - because you don't have to waste precious RAM space adding labels to the database. (We've got 64 KB of RAM in the C64; only about 30 KB of which are reserved for the label database.)

To implement this I need to add two line parsing variables to keep track of the leading *'s; add a few lines of code to the labels database routines that circumvent its ordinary behavior, and add a few error traps to the codes that handle equates and label table pseudo-codes. Let me explain those last two bits.

So normally a label represents a program counter value were a line of code starts. We use this concept to name routines or jumping / branching points for later use. Thus, under ordinary conditions, when we reache a statement like /quit RTS, the "quit" label and value are saved to the database. Whereas when we reach a statement like BNE &loop, the "loop" label and value is loaded from the database so the BNE's argument can be determined. Yay.

But there's another way to force a label / value pair into the database and that's through the equate pseudo-code.

Equate Pseudo-Codes
LADS: print = $ffd2

TXULA: .= &print $ffd2 OR .= $ffd2 &print


The error trap here is that for an equate the &'s label can't start with the *.

As for the label table pseudo-code.... This is actually one of the things I was most proud of when putting Txula together. My LABView x-platform assembler had this ability and I wanted my fork to gain it. With this pseudo-code I'm able to make lists or tables that invoke the label's values, it would look like this

Lable Table Pseudo-Codes
.#= loop print quit


(this version, .#=, lays the values out as 2 bytes in lo/hi order) But, because anything starting with the * refers not to labels but to the program counter value, I can't have .#='s arguments start with the * either. I augment to code to trap that as an error.

Anyway, instead of writing, that's my afternoon. Amazingly, for such a major to do, so little to change at all.
abrasax: (c64)
In regards to my 6502 Assembler, a project I finished last week (was it last week?). So I awoke today with the strangest idea about how to include a functionality from other assemblers. I mean using the current program counter as the basis of an argument. In those contexts you'd often see statements like BCC *+9, the * referring to the current program counter value, the +9 or +,- anything being an offset to that. It's an alternative to using absolute values or labels. LADS didn't implement that; neither does my fork. But now I've got the urge to add that. LOL It wouldn't be too hard, either.
abrasax: (Default)
I'll preface this by specifying it's only valid for the C64's BASIC v2 and, obvs, 6502 assembly. Further, BASIC didn't require spaces between keywords & arguments; in fact, BASIC programs were smaller and faster when the spaces were omitted. Even further - and ridiculously technical - the C64 used PETSCII not ASCII (see C64 PETSCII Codes). And yet another point of order, values will be given in $HEX / DECIMAL the first time you see them.

( ... go ahead jump right into the cut ... )
abrasax: (nostalgia)
Whilst I'm bored at work waiting between meetings, I'm going to take the opportunity to write about my other geeky hobby, retro!programming.

( ... this sure isn't fanfic anymore ... )

Profile

abrasax: (Default)
Abraxas

Badges

NSFW/18+LGBT PrideBelieves in ScienceFilm BuffWriterPhotographerAvatarVarang from Avatar Fire and Ash

November 2026

S M T W T F S
1 2 3 4 5 6 7
8 9 10 11121314
15161718192021
22232425262728
2930     

Syndicate

RSS Atom

Style Credit

Powered by Dreamwidth Studios
Page generated 2026-11-11 08:59 pm