ASM502 - a new 6502 assembler.. (WIP)

You need an actual VIC.

Moderator: Moderators

orac81
Vic 20 Newbie
Posts: 11
Joined: Fri Jan 06, 2023 12:07 pm
Location: UK
Occupation: coder

ASM502 - a new 6502 assembler.. (WIP)

Post by orac81 »

ASM502
--------

ASM502 is a 6502 assembler written in C99-compliant C code. It is small and light, and yet implements a useful subset of CA65 functionality.
asm502-115a.zip
(62.49 KiB) Downloaded 19 times
I can hear everyone shout "we dont need another 6502 assembler", and they are probably right! In defence ASM502 has a few interesting points - it is (fairly) modern, compatible with a useful subset of CA65, and it is small, it can even compile/run (with cc65) on a Commodore 64 or Plus 4.

ASM502 uses standard 6502 assembler syntax.

To compile a 6502 assembler source "myprog.s" use:
asm502 myprog.s myprog.prg
(Specify correct name/path at start, ie: ./asm502.elf myprog.s myprog.prg )
ASM502 generates the 2 byte header with the start address (from the .ORG statement in the code).
If you want to save the listing file use:
asm502 myprog.s myprog.prg >myprog.lst
Load "myprog.prg" on your emulator (or real comp) and start with RUN (or SYS XXXX etc).


Internally ASM502 works with 32 bit numbers (ie the default C integer) depending on the C compiler options used.
Numbers can be decimal (default), hex (precede with $) or binary (precede with %) ie:
.byte 160, $A0, %10100000 ; Number 160 in decimal, hex, binary..

Unary operators can preceed an expression:
<(expression) ; Low byte of expression
>(expression) ; High byte of expression
-(expression) ; Negate expression

ASM502 supports variables and can evaluate complex expressions. It uses C-style operators "<<,>>,=,!=,<,>,&,|,^,+,-,*,/,%".

expr1 << expr2 ; Shift expr1 left by expr2
expr1 >> expr2 ; Shift expr1 right by expr2
expr1 = expr2 ; True if equal
expr1 != expr2 ; True if not equal
expr1 < expr2 ; True if less
expr1 < expr2 ; True if more
expr1 & expr2 ; Bitwise AND
expr1 | expr2 ; Bitwise OR
expr1 ^ expr2 ; Bitwise EOR (EXCLUSIVE OR)
expr1 + expr2 ; Add
expr1 - expr2 ; Subtract
expr1 * expr2 ; Multiply
expr1 / expr2 ; Divide
expr1 % expr2 ; Modulus (remainder of division)

A variable must start with upper/lower case letter, then include numbers or underlines. ie:

My_var1 = (($123 + %1010 + 1234) * 2) & $ffff ; Assign const val to (My_var1)
.word (My_var1 >> 1) + (33 * $22), $abc1, 0 ; Use that in .word code definition..

Here are some example lines:

; Comments follow a semicolon.
label: ; lable can be a destination for a branch or jump or data.
lda #65 ; 6502 load accumulator with decimal 65.
.byte 1,2,3,4 ; Define 4 bytes.
.word $1234, $abcd ; Define 2 words (same as: .byte $34,$12,$cd,$ab)
.byte <label, >label ; Low and high byte of label


ASM502 supports a subset of assembler macro/conditional directives.

*=(expression) ; Set start-address of assembly code..
.org (expression) ; Set start-address of assembly code.. (alternative to *=.. )
.byte (expression),"strings".. ; Define some bytes in-line
.word (expression),(expression).. ; Define some 16 bit words inline (in lo/hi byte order)
.end ; Terminate assembly.

.if (expression) ; Conditional compile following code if (expression) non-zero..
; asm code here ..
.else ; Compile following code if (expression) is zero..
; asm code here..
.endif

.define var expression ; This is the same as "var=expression". more complex macro .define not (yet) implemented.

Most more complex directives (ie: macros) are not (yet) implemented.

Here is a more complete simple example program to print some text.

;---------------------------------------------------------------------------------------
; Simple program to print some text.

* = 828 ; Put code in C64 tape buffer, call with SYS 828.. (change for non-commodore computers..)
printchar = $ffd2 ; Routine to print accumulator as char on screen (change for non-commodore computers..)
IS_C64=1 ; Set variable IS_C64 to 1

printtext: ; jsr printtext starts this program.
ldx # 0
printloop: ; loop point.
ldy textdata,x ; get character to print
beq printdone ; Zero terminates print
txa
pha ; Save X on stack
tya
jsr printchar ; Print character in Accumulator
pla
tax ; Get X
inx
bne printloop
printdone:
rts

textdata:
.if IS_C64 ; Only compile following if IS_C64 is non zero
.byte "HELLO C64! ",0 ; Define some text bytes, zero at end.
.else
.byte "THIS IS NOT A C64! ",0
.endif
;---------------------------------------------------------------------------------------

to compile this program, cut and paste the above to a new text file called "testpr,s", then compile with:
asm502 testpr.s testpr.prg
Load "testpr.prg" on your emulator (or real comp) and start with SYS 828.

There are more extensive code examples included with ASM502.


ASM502 notes
--------------

The source code "asm502.c" is included, and released under the GNU GPL3 licence (see end of this document).

As things stand this program is a "work in progress". It started as an adaption of an earlier assembler of mine when I wanted something simpler and smaller than the CA65 (the CC65 assembler). Now CA65 is a very good assembler, but by necessity it has to deal with far more complexity due to it being part of a C compiler - segmentation, object files, library formats etc.

Compiling the ASM502 single-file source just needs a C99 compatible C compiler, and is as simple as:
cc asm502.c -o asm502 -Os # in Linux..

I have included pre-built binarys for 32 bit Windows and Linux, but if you have a C compiler I recommend that you just build a binary for your own system.

ASM502 is a work-in-progress, and has plenty of omissions, and some bugs too, but it is useable, so I thought I should put it out anyway - I havent done anything to it for a long while now.
The .include command is not included yet, but it would not be difficult to add. Other things like macro definitions and procedures would require more work, but are possible.

ASM502 is a two-pass assembler. As it stands it simply allocates the memory for the source file and loads it in one block, but it is designed so that it could compile the source line-by-line. That would be useful to make it more effective on platforms with limited memory.
It can, and has been compiled on minimal platforms like the Commodore 64, although some tweaks to memory allocation for arrays might need looking at first. For simplicity, source files on Commodore platforms should be converted to upper case - again, this could be fixed.

In the examples folder are portable assembler sources (+binaries) for FREAX (nice 2k game for c64/vic20/c16), LIFET (game of life in 126 bytes) and a few other odd demos and examples. These will also compile with CA65.

In the end I have found ASM502 interesting and useful, so maybe you will too!
Last edited by orac81 on Mon Apr 22, 2024 9:35 am, edited 1 time in total.
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

You're right. There are enough assemblers nobody uses already. ;)
I like it for being small and written in C. And the parsing part with expressions. What I do not like is that the code *looks* unstructured and could be readable better (after a treatment with dos2unix and "indent -kr -i4").

Port it to the VIC!

p.s.: And turn your post into a README?
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
wimoos
Vic 20 Afficionado
Posts: 349
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by wimoos »

Hello orac81,

If I can make a suggestion for a "new" assembler: why not one that optimizes automatically ?

During assembly, keep a hold of the state of the machine and comment on instructions that do not affect that state. For example: if it can be known that the carry is set, then do not assemble a SEC, but comment in the listing that that instruction was ignored.
Same for a memory location that is known to hold a certain value, then do not store that value again.
Or, easier to start with, comment out NOPs.

More optimizations could be found, but that gives room for more creativity.

And, 64 kilobytes of addressing space is huge for a 6502, but not much for modern day systems, so I would expect this to be feasible.

Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

wimoos wrote: Wed Apr 17, 2024 1:41 am If I can make a suggestion for a "new" assembler: why not one that optimizes automatically ?
Very good idea. Would be quite a win when using lots of macros.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
orac81
Vic 20 Newbie
Posts: 11
Joined: Fri Jan 06, 2023 12:07 pm
Location: UK
Occupation: coder

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by orac81 »

Thanks for the comments.
As for Indentation in asm502.c - change tab width to 8 and it should look ok. I should just convert tabs to spaces.
Yes it needs tidying, although I try and use a kind of C++ structures in C by adding short class-style prefixes to var/proc names, ie: var_ for variable code, asm_ for assembler itself etc..
That first post is in the zip as asm502.txt.

It should compile and run for a 32k VIC20 ok, I have got versions running for c64 and apple2, but it was done a while back. I want to check before posting them. The c64 version is 12k. As I said asm502 just grabs a big chunk of mem for the source, it would be better if it processed line by line on those platforms, otherwise you are limited to small ASM programs.

As for optimization, yes "dead code elimination" would be beneficial for macros and hi level code generators. You have to be careful of self modifying code..

As a side note, the 6502 lacks a really good optimising C compiler , particularly for byte manipulation, nice as cc65 is..
I would love if someone made a small assembler like ASM502 for the ARM, targeting the pi, android, Arduino, blue pill etc, so you didn't have to run an SDK full of bugs taking a gigabyte or more..

Anyway I use ASM502 for FREAX, so it has at least one user!
groepaz
Vic 20 Scientist
Posts: 1190
Joined: Wed Aug 25, 2010 5:30 pm

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by groepaz »

I would love if someone made a small assembler like ASM502 for the ARM, targeting the pi, android, Arduino, blue pill etc, so you didn't have to run an SDK full of bugs taking a gigabyte or more..
Just build GAS for ARM? For all those modern CPUs it really doesn't make a lot of sense to make a custom assembler - GAS will support them anyway :)
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

orac81 wrote: Wed Apr 17, 2024 5:48 am As a side note, the 6502 lacks a really good optimising C compiler , particularly for byte manipulation, nice as cc65 is..
There's a LLVM with 6502 target but lacking a stdlib AFAIR.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
User avatar
Mike
Herr VC
Posts: 4843
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by Mike »

orac81 was more cautious in the response, but anyway:
wimoos wrote:During assembly, keep a hold of the state of the machine and comment on instructions that do not affect that state. For example: if it can be known that the carry is set, then do not assemble a SEC, but comment in the listing that that instruction was ignored. Same for a memory location that is known to hold a certain value, then do not store that value again.
In general, with user-written code, an assembler will not have a good idea about these conditions. It amounts to execute arbitrary code already in the assembler which, IMO, is not its job.
Or, easier to start with, comment out NOPs.
... which will then break any code where the programmer wrote the NOP(s) in cold blood, for timing purposes.

That being said, you find this kind of optimizations in compiler backends, where the code generator first produces straightforward code with foreseeable side effects. The latter are then the conditions to apply peephole optimizations, on the source being fed to the assembler. The assembler then is expected to do a 1:1 translation.
pixel wrote:And turn your post into a README?
+1
Merytsetesh
Vic 20 Amateur
Posts: 41
Joined: Sat Mar 02, 2024 8:57 pm
Location: Canada

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by Merytsetesh »

Mike wrote: Thu Apr 18, 2024 1:18 am
wimoos wrote:During assembly, keep a hold of the state of the machine and comment on instructions that do not affect that state. For example: if it can be known that the carry is set, then do not assemble a SEC, but comment in the listing that that instruction was ignored. Same for a memory location that is known to hold a certain value, then do not store that value again.
In general, with user-written code, an assembler will not have a good idea about these conditions. It amounts to execute arbitrary code already in the assembler which, IMO, is not its job.
It's not the assembler's job, but it is the optimiser's. :-)

If you break the code down into basic blocks, this becomes a more tractable problem. That said, if the code is self-modifying (which would take some chunky analysis to determine) then this becomes dangerous because the code might rely on the byte of the SEC instruction existing, or it might affect the timing.

I am not sure that optimisation is the best option. What I might suggest is that the assembler makes suggestions to the user for possible code issues or infelicities (and that there's a flag to prevent output of those suggestions) and then the user gets the choice on whether to act on them.
groepaz
Vic 20 Scientist
Posts: 1190
Joined: Wed Aug 25, 2010 5:30 pm

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by groepaz »

In general, with user-written code, an assembler will not have a good idea about these conditions. It amounts to execute arbitrary code already in the assembler which, IMO, is not its job.
Peephole optimization is well possible in an assembler. Actually Daniel Dallmann (Lunix) wrote such optimizer for 6502 decades ago. How useful it really is in practise is debatable though :)

What i i really would like to see would be something similar, which can suggest alternative instructions (ie undocumented opcodes) for certain code sequences - because those things are often not obvious.
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

groepaz wrote: Thu Apr 18, 2024 11:40 am What i i really would like to see would be something similar, which can suggest alternative instructions (ie undocumented opcodes) for certain code sequences - because those things are often not obvious.
That would even be nice without undocumented ones. I'd break them down into a bit-level IR and try to re-assemble them into instructions. Given CPU power these days....

But just to agree with Mike: a true optimizer in cc65 is overdue. I can't make heads and tails of the internal interfaces yet.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
groepaz
Vic 20 Scientist
Posts: 1190
Joined: Wed Aug 25, 2010 5:30 pm

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by groepaz »

cc65 cant really do more than it does now (peephole optimizations) - it has to be rewritten to use an IR first - acqn has been working on it iirc, check his repos
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

groepaz wrote: Thu Apr 18, 2024 12:59 pm cc65 cant really do more than it does now (peephole optimizations) - it has to be rewritten to use an IR first - acqn has been working on it iirc, check his repos
There's just so much stuff that should've never been written manually, it looks easier to port lcc to 6502 (Latest version is worth a look.)
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
groepaz
Vic 20 Scientist
Posts: 1190
Joined: Wed Aug 25, 2010 5:30 pm

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by groepaz »

Yeah good luck :) What makes cc65 strong is the library and its ecosystem anyway, and if you rely on the optimizer of a 8bit compiler, you are doing it wrong :)
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
User avatar
pixel
Vic 20 Scientist
Posts: 1360
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: ASM502 - a new 6502 assembler.. (WIP)

Post by pixel »

groepaz wrote: Thu Apr 18, 2024 2:53 pm Yeah good luck :) What makes cc65 strong is the library and its ecosystem anyway, and if you rely on the optimizer of a 8bit compiler, you are doing it wrong :)
:D No, I mean 'lcc' is worth a look if interested in compiler design. I'd port Small-C to run natively if I could (for TUNIX).
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
Post Reply