Page 5 of 9

Re: Which assembler could I possibly use ?

Posted: Thu Jun 19, 2025 5:48 pm
by soci
migry wrote:
Thank you for replying to the issues I encountered. I will go back and try the option to get a simple binary file. Nice to know that the author is contactable.
There's also an e-mail address as the bug tracker needs registration. Prompt answers are not guaranteed, needs a bit of a luck sometimes.
migry wrote:
TBH I was very impressed with the documentation. In fact it was so detailed I wasn't sure if there was a switch to solve my binary dump issue or if I had simply not looked in the right place in the documentation :-) .
I've grouped the output format switches close so if something is not there it needs to be done by manually or with external tools. For example more complex header files for emulator cartridges or disk images. But most of the simple formats are covered now.

There's still room to improve on the documentation, after the last release there was a request to improve the repetitions section with more examples, and rightly so.
migry wrote:
Nevertheless there were several cases where a string was mixed with a byte or list of byte on a single line. I think when I have used ".db" in the past (I forget the processor - 8088?). it was possibly to mix text and bytes together using the '.db' directive, useful when CR and LF needed to terminate a string.
The .text directive existed in the native assembler it was originally modelled of, so it was there from the beginning. For a while .text and .byte were even working the same. Later it was split so .byte can be used make sure every item is a single byte, as that's more useful than an alias of .text which does strings.

While .text is for strings it still accepts small integers of 0-255 specifically for numeric control character use like CR/LF.

I rarely interrupt a string to insert control characters/sequences any more. Since it's possible to use custom encodings it's easy to define escape sequences which emit them when used in strings.
migry wrote:
e.g.

Code: Select all

 .byte 6,12,15,"ACORN ATOM",10,10,13
           lda #$82

 .byte "NAME"
   nop
I believe that the string print is terminated by a negative byte (not just a zero value), which saves a few bytes throughout the OS code. In some places the following instruction is a nop since the next instruction has a positive opcode.
What a dirty trick :) They could have just put the sign bit high on the last character, like it's done on MS BASIC keywords. Sure the sign needs to be removed and the loop is slightly different but removing the extra NOPs might make it still worth.

That's so common that there's a directive to set the high bit at the last byte:

Code: Select all

.shift 13, 10, "abc"   ; last byte is "c" + $80
This also comes from the native assembler and named so because capital letters had the high bit set.

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 1:19 pm
by teamtempest
Quote:
That's so common that there's a directive to set the high bit at the last byte:
It's a simple enough directive, sure. So simple that it's also easily implemented as a macro, if the assembler's macro language is powerful enough.

Doing it the macro way has the advantage of allowing for the possibility of a programmer realizing that any encoding desired can be created the same way. Thus liberating from the idea that what it is possible to do is limited to what a particular assembler has "built-in". IMO, anyway.

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 1:39 pm
by drogon
teamtempest wrote:
Quote:
That's so common that there's a directive to set the high bit at the last byte:
It's a simple enough directive, sure. So simple that it's also easily implemented as a macro, if the assembler's macro language is powerful enough.

Doing it the macro way has the advantage of allowing for the possibility of a programmer realizing that any encoding desired can be created the same way. Thus liberating from the idea that what it is possible to do is limited to what a particular assembler has "built-in". IMO, anyway.
In ca65 from the cc65 suite, such a macro looks like:

Code: Select all

;********************************************************************************
; Macro strTop:
;       Include a string but set the top-bit of the last character
;********************************************************************************

.macro strTop   str
        .repeat .strlen(str)-1,I                        ; All but the last
          .byte    .strat(str,I)
        .endrep
        .byte   .strat(str,.strlen(str)-1) | $80        ; The last character
.endmacro
It's not pretty but easy to understand once you have the hang of it's string manipulation operators. It's used like:

Code: Select all

    strTop "FOR"
More power to your macro...

-Gordon

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 6:01 pm
by soci
The equivalent is easy to do:

Code: Select all

strTop .function _s : bytes
       .text _s[:-1], _s[-1] | $80
       .endf

       .strTop "test"
It converts the parameter to bytes first and then cuts of the last one and sets the sign bit there. Same could be done directly on the string as well but that would break escape sequences at the end of the string.

Same like the ca65 macro it has the shortcoming that only one parameter can be used and that it isn't verified that the sign bit isn't set already somewhere. Can be made smarter of course:

Code: Select all

strTop .function *s
_s      := bytes(s) .. ...  ; concatenate all
         .cerror bits(_s)[7::8] > 0, "Sign bit already set somewhere"
         .text _s[:-1], _s[-1] | $80
         .endf

         .strTop 5, "tet", 13, 10
But it'll never be quite the same:

Code: Select all

test.asm:1:29: error: most significiant bit must be clear in byte
         .shift 5, "te{white}St", 13, 10
                             ^
That reminds me of something recent. I got a request to add a floating point directive to output 40 bit MBF, because it's popular (depends). I gave an example macro in response as it's not difficult to do that manually.

But that's not good enough as it doesn't behave exactly the same like a regular data directive. Sure that was an example so it was kept simple.

Made a proof of concept directive, easy enough and works as expected. But if I'd add this one what about the other variants? There are just too many floating point formats around to add a directive for each.

And so there isn't one yet, but might be some day. It seems not everyone likes the challenge to write their own even if the tools are there.

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 6:17 pm
by BigDumbDinosaur
teamtempest wrote:
It's a simple enough directive, sure. So simple that it's also easily implemented as a macro, if the assembler's macro language is powerful enough.

The Kowalski assembler has a pseudo-op called .ASCIS, which will invert bit seven of the last byte of a character string.  If I write .ASCIS "ABC", the assembler will generate $41 $42 $C3.  However, if I write .ASCIS $C1,$C2,$C3, which would be "ABC" with bit seven set in each character, the assembler will generate $C1 $C2 $43.  So what .ASCIS is doing is exclusive-ORing bit seven in the final character with %10000000.

Although the Kowalski assembler’s macro language is quite powerful, it doesn’t have the ability to pick apart a string that is a parameter to a macro invocation.  Hence writing a macro to always set bit seven of the final character, even in a case where the submitted string is $C1,$C2,$C3, doesn’t seem to be possible.

I have yet to find a use for .ASCIS.  I use null-terminated strings in most of my programs, and Pascal-style strings in a few instances.  For generating the latter, the Kowalski assembler has the .LSTR and .STR pseudo-ops.  I suppose if I were writing a language compiler/interpreter I could find a use for .ASCIS, since the resulting strings will always be one byte shorter than null-terminated or Pascal-style equivalents.  It would depend on how desperate I might be to minimize program size in raw bytes.

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 7:14 pm
by barnacle
This is one reason I don't particularly like macros and use them only when I have to... there is no standard definition or expectation about how the macro processor works.

It's enough of a pain that different assemblers don't always have the same directives, though mostly they have equivalents, but to be honest I'd rather make it explicit with something like

Code: Select all

    db 'A','B','C'+$80
which is clear and unambiguous irrespective of assembler and easy to translate between them, if a slight pain when writing the initial code.

Neil

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 8:04 pm
by GARTHWILSON
With the limited number of assemblers I've used, it seems to me that although there may be differences in the way a macro is defined, its usage should be able to be made consistent from one assembler to another.  Regardless, certainly there are simple ones that should always be worth it, like where I see people here taking for lines for ASL, ASL, ASL, ASL, where they could easily make a macro and call it ASL4X and take only one line.

Re: Which assembler could I possibly use ?

Posted: Fri Jun 20, 2025 11:12 pm
by barrym95838
GARTHWILSON wrote:
... call it ASL4X and take only one line.
But it needs to be defined, and so it'll have to be used several times to break even. 10KB of Applesoft ROM contains one instance of four or more consecutive ASLs, and it's actually six in a row, which seems a bit silly since

Code: Select all

    and #7
    ror
    ror
    ror
is one byte smaller and four cycles faster.

Re: Which assembler could I possibly use ?

Posted: Sat Jun 21, 2025 12:14 am
by GARTHWILSON
barrym95838 wrote:
GARTHWILSON wrote:
... call it ASL4X and take only one line.
But it needs to be defined, and so it'll have to be used several times to break even.
I think you're thinking of a subroutine.  A macro is not a subroutine for the target computer.  It will take a little more memory in the computer that's assembling the code, but the resulting code is the same, in this case being four ASL's in a row with no JSR or RTS.  When you look at the resulting machine code, you won't be able to tell if a macro was used or not.

Re: Which assembler could I possibly use ?

Posted: Sat Jun 21, 2025 4:56 am
by barnacle
Looking at the code for Neo Tiny Basic, there are (I think) three cases where I use macros:
  • To get around a deficiency in the assembler, where I needed three-byte versions of instructions it was automatically generating as zero-page versions and it had no mechanism to instruct it to do that.
  • To automate simple groups of instructions to save my brain; e.g. making sure I loaded sixteen bit variables (Y:A) in the right order.
  • To generate a new class of directive, ENUM, allocating serially incrementing values to variables (similar to the same function in C)
Which seems to cover the options discussed upthread, I think. More than I initially expected - though NTB is probably the biggest slab of 6502 machine code for which I have been responsible.

Neil

Re: Which assembler could I possibly use ?

Posted: Sat Jun 21, 2025 10:42 am
by drogon
I do like macros for many reasons.

One - as I posted above to create strings with the last character having the top bit set. This is used in my TinyBasic to delimit keywords - because I really do want to save that byte that would otherwise be a BCPL style string (first byte is length and Pascal is a Johnny come lately), or C style zero terminated. It makes a difference when trying to squeeze everything + kitchen sink into 4KB...

Another is conditional assembly - where I have the choice of in-lining code or calling a subroutine - the in-lines code is faster, but the subroutine call saves bytes, so decisions to make. It's tricky to implement, so for e.g. the case of incrementing the 'cursor' - a pointer to the next byte in the source code I have in a header file:

Code: Select all

;*********************************************************************************
;* incCursor    
;*      Increment the Cursor pointer
;*      In-line Macro, or JSR to code...
;*********************************************************************************

.if (useIncCursorCode)

        .global incCursorCode
.macro  incCursor
        jsr     incCursorCode
.endmacro

.else

.macro  incCursor
.local  over
        inc     cursorL
        bne     over
        inc     cursorH
over:
.endmacro
.endif
In the source file I have:

Code: Select all

.if (useIncCursorCode)
.proc   incCursorCode
        inc     cursorL
        bne     :+
        inc     cursorH
:       rts
.endproc
.endif
and in a globally included header file I have:

Code: Select all

useIncCursorCode        =       1
which I can set to 1 or 0 to test/check either way. The rest of the code doesn't need to change as long as there is simply:

Code: Select all

    incCursor
as an instruction. I just change the flag and re-assemble then check object file size and execution speeds.

I have several bits in my TinyBasic and many like this in my Acorn-like Operating System for my Ruby Boards. Also the Cintcode VM for my BCPL system does it this way too in many cases, although in that case the aim is for speed not space saving - it's already slow enough...

Over the years, as65 hasn't let me down in this respect - but like everything it just takes a little while to get right.

-Gordon

Re: Which assembler could I possibly use ?

Posted: Sat Jun 21, 2025 4:36 pm
by 6502inside
Quote:
This is one reason I don't particularly like macros and use them only when I have to... there is no standard definition or expectation about how the macro processor works.
That's what attracted me to xa65 in the first place: it's more or less a subset of the C preprocessor. You may or may not like it (of course, I do) but at least it can be understood by other tools.

Re: Which assembler could I possibly use ?

Posted: Sat Jun 21, 2025 6:11 pm
by barrym95838
GARTHWILSON wrote:
I think you're thinking of a subroutine.  A macro is not a subroutine for the target computer.  It will take a little more memory in the computer that's assembling the code, but the resulting code is the same, in this case being four ASL's in a row with no JSR or RTS.  When you look at the resulting machine code, you won't be able to tell if a macro was used or not.
No, I meant source "keystrokes" when I mentioned the "break even" point. I can appreciate some of the advantages of macros, but in my hobby use case I have never felt the urge or obligation to utilize them. Proper comments are far more useful to me. In fact I prefer to reverse-engineer .LST files over .ASMs when available, because the macros are expanded for me and I don't have to scroll and click around to look for the definitions. (Admittedly, ASL4X is an easy one, but the more complex ones can be a bit frustrating for me, especially if the source is spread over several files).

Re: Which assembler could I possibly use ?

Posted: Fri Aug 01, 2025 8:09 pm
by Virtual1
(first post, just joined)

So an instructor loaned a coworker an Apple IIe (unenhanced) to see if he could get it working. We fixed some minor electrical problems and now it's back to nostalgia-land for me. No floppies to use ATM, (and certainly nothing bootable) so I've been playing with Apple][js to re-familiarize myself with the Apple II. I used to have most of the common opcodes, rom addresses, soft switches, zero page, etc memorized but it's taking time to come back.

I used Merlin Pro back the day, and realize I need something, as assembling by hand is a big pain. For now I've just been opening the monitor and pasting in what I was editing by hand in a text editor. So here it comes... you'll either be in the "OMG that's so cool!" or the "KILL IT WITH FIRE!" camp.

I wrote an assembler... in Excel.

"work with what you have", right? It's pretty basic, supports jump/branch labels, address/constant labels, calculates branches and jumps, translates assembly to byte code with addresses, ready to paste into the monitor. Let me know if you'd be interested to play with it.

Re: Which assembler could I possibly use ?

Posted: Fri Aug 01, 2025 8:20 pm
by BigDumbDinosaur
Virtual1 wrote:
(first post, just joined)

Welcome!

Quote:
...I wrote an assembler... in Excel.

Microsoft!  Ugh!!!  :D

You might get a similar reaction from others here.  :wink:

Quote:
"work with what you have", right? It's pretty basic, supports jump/branch labels, address/constant labels, calculates branches and jumps, translates assembly to byte code with addresses, ready to paste into the monitor. Let me know if you'd be interested to play with it.

Yes, but can it do macros?  :P

I and a number of others around here use the Kowalski editor/assembler/simulator for 6502 development.  You can get it here.  Regrettably, it too runs on Billy-ware, but is otherwise an excellent package with lots of features and enhancements.

If you do some sleuthing, you might be able to track down a copy of Merlin for the Apple II series.