6502 assembler for 6502?

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
and3rson
Posts: 163
Joined: 17 Feb 2023
Location: Lviv, Ukraine
Contact:

6502 assembler for 6502?

Post by and3rson »

I'm wondering if there are any implementations of 6502 assemblers written in 6502 assembly itself (alternatively, written for CC65) that support common features like labels. Basically, a program that can be given string as an input and produce machine code as a result.
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: 6502 assembler for 6502?

Post by drogon »

I'm sure there are many - back in the day (c1980) I used something called TED II+ on the Apple II for example...

And of-course there's the one built into BBC Basic ...

Assembler ROMs for the AIM-65...

And I'm sure many many more..

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: 6502 assembler for 6502?

Post by BigDumbDinosaur »

and3rson wrote:
I'm wondering if there are any implementations of 6502 assemblers written in 6502 assembly itself (alternatively, written for CC65) that support common features like labels. Basically, a program that can be given string as an input and produce machine code as a result.

Commodore’s MADS (C-64) and HCD65 (C-128) packages were full-featured assemblers written in 6502 assembly language.  HCD65 emitted an object file in MOS Technology symbolic format (similar to Motorola S-record format), which was then submitted to a linker to produce the final binary.  As I recall, the linker made it possible to relocate the resulting binary to an entirely different starting address, with static address references being fixed up.  That feature made it possible to develop code that could run on the stack.

I don’t know if the source code for either is available.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: 6502 assembler for 6502?

Post by floobydust »

I used the Commodore MADS package on the C64 for many years back in the 80's. I did a lot of code using that package. Overall a nice setup with an editor and dos wedge. The real bottleneck was the Commodore disk drive... initially using a 1541 and later a 1581 which did improve the performance.

On another note, Richard Leary's DOS/65 has an assembler (written in 6502 assembly) that runs on the 6502 and uses DOS/65 for file I/O. The entire source is available as well. I've used this quite a bit recently for testing of my recent DOS/65 3.20 version. It's a good 2-pass assembler, but it only supports the original NMOS 6502 instructions/addressing modes.
User avatar
Proxy
Posts: 746
Joined: 03 Aug 2018
Location: Germany

Re: 6502 assembler for 6502?

Post by Proxy »

it would be amazing if it were possible to compile the cc65 utlities with itself, so you could have a native C compiler, Assembler, and Linker. but i think 64k is simply not enough to run any of them natively.

of course another option is to write something yourself (either in C or directly in assembly), though that arguably takes more effort than porting something existing.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: 6502 assembler for 6502?

Post by barnacle »

Back in the day I used an in memory assembler (an EPROM on the expansion board) for the Tangerine Microtan 65. TANSOFT, I think. That and some other options here: http://www.microtan.ukpc.net/pageAssemblers.html

I also used - mostly for development SBCs - Avocet running under CP/M on a z80 machine to generate binaries.

Neil
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: 6502 assembler for 6502?

Post by drogon »

Proxy wrote:
it would be amazing if it were possible to compile the cc65 utlities with itself, so you could have a native C compiler, Assembler, and Linker. but i think 64k is simply not enough to run any of them natively.
I did try - I gave it one-shot and failed miserably. It's just not going to work...

Proxy wrote:
of course another option is to write something yourself (either in C or directly in assembly), though that arguably takes more effort than porting something existing.
It might be nice to make it modular enough to work on other systems, but that could be quite hard when it comes to filing system interfacing. Also things like I have started on an assembler myself, but it's in BCPL, so not much use to anyone other than me, really... If it's written in ASM on another system then it might limit who can actually assemble it in the first instance and so on...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
Proxy
Posts: 746
Joined: 03 Aug 2018
Location: Germany

Re: 6502 assembler for 6502?

Post by Proxy »

you don't really need a file system if the assembler works like a BASIC interpreter and includes it's own editor, with optional LOAD and SAVE commands that the user can implement themself.
Dietrich
Posts: 45
Joined: 01 Jan 2003

Re: 6502 assembler for 6502?

Post by Dietrich »

You might want to have a look at my assembler at https://github.com/Dietrich-L/CPM-65/tree/main/ASM
It is nativ, has MOS 6502 opcodes only and is very fast. No macros though.

The input is a text file, output is the assembled file and a label file. It is 6k in size and easy to port. However you need a file system to read the source file in 256 byte chunks and write the output files also in 256 byte chunks.

If you need any assistance, let me know.

Dietrich
My system: Elektor Junior Computer, GitHub https://github.com/Dietrich-L
dmsc
Posts: 154
Joined: 17 Sep 2018

Re: 6502 assembler for 6502?

Post by dmsc »

Hi!
Proxy wrote:
you don't really need a file system if the assembler works like a BASIC interpreter and includes it's own editor, with optional LOAD and SAVE commands that the user can implement themself.
In the Atari 8-bit computers, two popular assemblers worked with this "BASIC like" editor: The original Atari Assembler Editor ( https://en.wikipedia.org/wiki/Atari_Assembler_Editor ) and the MAC/65 macro assembler ( https://en.wikipedia.org/wiki/MAC/65 ).

Source for the MAC/65 assembler is available, it is for the cartridge version that uses a bank-switched cart: https://atariwiki.org/wiki/Wiki.jsp?pag ... 651.011986 , it was used a lot because it tokenized the sources, making it very fast and allowing bigger sources.

There are a lot of assemblers for the Atari 8-bit, with and without support for macros and relocatable output. Some like Fast Assembler https://github.com/HolgerJanz/FastAssembler are still being updated today. Here is a little list (use google translate): http://atariki.krap.pl/index.php/Asembler

Have Fun!
leepivonka
Posts: 168
Joined: 15 Apr 2016

Re: 6502 assembler for 6502?

Post by leepivonka »

Another option is to run a 6502 assembler in FORTH hosted on a 6502.

If you're OK with a FORTHish syntax (to reuse the FORTH command line parsing) the assembler logic is straightforward.

Some 6502 implementations are
"typists assembler" in Tali FORTH,
& 6502 assembler in FIG FORTH.

Here is the console log of a 65816 example:

Code: Select all

\ FORTHish assembler simple demo  ok
  ok
: UM*S ( u1 u2 -- ud ) \ start a subroutine (word) definition  compiled
  \ ud=u1*u2  simple multiply  compiled
  \ https://forth-standard.org/standard/core/UMTimes  compiled
  [ \ shift FORTH interpreter from compile to interpret state   ok
  0 ## lda, \ init product hi  ok
  2 d,x lsr,  \ initial shift u1  ok
  16 ## ldy, Begin,  \ for each u1 bit  ok
    IfCs,  ok
      clc, 0 d,x adc,  Then,  ok
    rora, 2 d,x ror,  \ shift right product & u1  ok
   dey, UntilEq,  ok
  0 d,x sta,  \ store product hi, product lo already in place  ok
  ]  \ shift FORTH interpreter from interpret to compile state  compiled
  ;  \ end the subroutine (word) definition  ok
  ok
SeeLatest  \ disassemble last word
04DB A90000     LDA #$0000 {' SInIndx0}
04DE 5602       LSR $02,x
04E0 A01000     LDY #$0010 {' SInIndx2}
04E3 9003       BCC $04E8 {UM*S+000D}
04E5 18         CLC
04E6 7500       ADC $00,x
04E8 6A         RORA
04E9 7602       ROR $02,x
04EB 88         DEY
04EC D0F5       BNE $04E3 {UM*S+0008}
04EE 9500       STA $00,x
04F0 60         RTS

 ok
  ok
1234 23456 UM*S D.  \ test the new subroutine 28944704  ok
  ok
  ok
: DUM/ModB ( uq_dividend ud_divisor -- ud_rem ud_quot )  \ unsigned divide 64/32=32,32  compiled
  [  ok
   8 d,x lda, LRefA @Word jsr,  8 d,x sta,  ok
  10 d,x lda, LRefA @Word jsr, 10 d,x sta,  ok
  inx, inx, inx, inx,  ok
  ' 2Swap jmp,  ok
  ok
 LDef @Word  ok
  asla, Tmp sta,  \ save dividend word & get next bit  ok
  16 ## ldy, Begin,  \ for each bit in word  ok
    6 d,x rol, 4 d,x rol, LRefR @8 bcs, \ rol dividend hi  ok
    6 d,x lda, 2 d,x cmp, 4 d,x lda, 0 d,x sbc, \ compare  ok
    IfCs,                                       \ if  ok
 LDef @8  ok
      6 d,x lda, 2 d,x sbc, 6 d,x sta,  \ subtract  ok
      4 d,x lda, 0 d,x sbc, 4 d,x sta,  ok
      sec, Then,  ok
    Tmp rol,  \ add bit to quotient word, get next dividend lo bit  ok
    dey, Untileq,  ok
  Tmp lda,  \ return quotient word  ok
  ] ;  ok
  ok
SeeLatest
04FC B508       LDA $08 {Tmp},x
04FE 201105     JSR $0511 {DUM/ModB+0015}
0501 9508       STA $08 {Tmp},x
0503 B50A       LDA $0A {Tmp+0002},x
0505 201105     JSR $0511 {DUM/ModB+0015}
0508 950A       STA $0A {Tmp+0002},x
050A E8         INX
050B E8         INX
050C E8         INX
050D E8         INX
050E 4CB08C     JMP $8CB0 {2Swap}
0511 0A         ASLA
0512 8508       STA $08 {Tmp}
0514 A01000     LDY #$0010 {' SInIndx2}
0517 3606       ROL $06,x
0519 3604       ROL $04,x
051B B00A       BCS $0527 {DUM/ModB+002B}
051D B506       LDA $06,x
051F D502       CMP $02,x
0521 B504       LDA $04,x
0523 F500       SBC $00,x
0525 900D       BCC $0534 {DUM/ModB+0038}
0527 B506       LDA $06,x
0529 F502       SBC $02,x
052B 9506       STA $06,x
052D B504       LDA $04,x
052F F500       SBC $00,x
0531 9504       STA $04,x
0533 38         SEC
0534 2608       ROL $08 {Tmp}
0536 88         DEY
0537 D0DE       BNE $0517 {DUM/ModB+001B}
0539 A508       LDA $08 {Tmp}
053B 60         RTS

 ok
  ok
$9abcdef0. $12345678. $98765432. DUM/ModB D.Hex Space D.Hex 1E9131AB 91430F8A ok
  ok
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 6502 assembler for 6502?

Post by GARTHWILSON »

leepivonka wrote:
Another option is to run a 6502 assembler in FORTH hosted on a 6502.
I was going to let this topic run its course before mentioning this; but since you brought it up, I'll chime in now.

I have Forth resident in my workbench computer's ROM for very quick development of applications.  Like they say, you can get 90% of the performance with only 10% of the code in assembly language—provided it's the critical 10%.  ...Or is it 95% and 5%?  Whatever.  [1]  Anyway, there are many situations where I want to do some short piece in assembly language for maximum performance, so I took a couple of hours one evening and wrote myself an assembler years ago.  Later I improved it a bit, and I still have further improvements in mind; but it was quick to write in its original form, and takes very little memory.  It's single-pass, and Forth keeps addresses on the stack during assembly so forward references get filled in later in the assembly when the target is encountered.  A pleasant surprise I got after I wrote it is that since it's in Forth, macro capability was automatic—I didn't have to do anything to get it.  This assembler is not suitable for writing whole applications in assembly language, only primitives, subroutines, ISRs, runtimes, etc..

Quote:
If you're OK with a FORTHish syntax (to reuse the FORTH command line parsing) the assembler logic is straightforward.

I hate the RPN syntax of most Forth assemblers, so I made mine to be more normal, so you could have for example LDA# 7 , instead of 7 ## LDA .  (The comma is part of it.  It lays down the operand.  All the LDA# does is lay down the A9 op code.  It doesn't care if you even put an operand on it, which can be handy when you want to do self-modifying code where the operand itself is a variable, rather than a reference to a variable.)  So leepivonka's '816 first primitive above, UM*S, would be written as:

Code: Select all

CODE  UM*S  ( u1 u2 -- ud )
      LDA#       0   ,
      LSR_DP,X   2  C,
      LDY#      10   ,       \ (I usually keep it in hex)
      HERE
         BCC 1$
             CLC
             ADC_DP,X  0  C,
 1$:     ROR_A
         ROR_DP,X   2  C,
         DEY
      BNE  GO_BACK
      STA_DP,X   0  C,
      GO_NEXT                \ Mine is not STC, which is
 \ ------------              \ why it's not RTS here.

No parsing is necessary.  The addressing mode is merged with the mnemonic, so you don't need a separate assembler vocabulary either, because for example assembly language's AND won't be confused with Forth's AND because in assembly language it's always AND#, AND_ZP, etc., never just AND.  You can put as many instructions on one line as you like.


[1]  The point is not that you can make the whole thing run 90% as fast as assembly, but rather that with a little assembly, you can get the speed-critical parts to perform as needed, while it doesn't matter for the rest.  "The rest" may be, for example, routines that scan and debounce a keypad, take care of auto key repeat delay and repeat speed, take in data or instructions on an RS-232 port and interpret them, etc..

An example from my own work is that I've had a machine-language ISR on my workbench computer playing back sampled aircraft audio at 24,000 samples per second while in Forth I was trying things by having the computer accept instructions as text over the RS-232 port and interpreting them.  The instructions could do things like change the sampling rate, move around in the recording, even modify the ISR on the fly.  So even though only a tiny percentage of it was not in Forth, I was producing the audio with 24,000 samples per second and doing other stuff at the same time, on my 5MHz workbench computer which was fast enough for it all.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
and3rson
Posts: 163
Joined: 17 Feb 2023
Location: Lviv, Ukraine
Contact:

Re: 6502 assembler for 6502?

Post by and3rson »

Dietrich - I'll try to use yours, looks very promising, thanks for sharing. I've tried writing my own in CC65, but it quickly went out of control and I've reached 8KB just with a simple tokenizer and mnemonic encoding. Not sure if my attempt is worth the time. Best case - I'll have an extremely simple and slow assembler that takes all my ROM... Here's my pitiful attempt: https://github.com/and3rson/6565 - though I'm probably going to abandon it. The only working part is tokenizer & mnemonic parsing.

Garth, leepivonka - Your FORTH stuff never ceases to amaze me, but I feel like I haven't yet reached the necessary state of mind to understand FORTH. :D I still appreciate your ideas, but I'll have to revisit them once I get better with FORTH.

Proxy - I too initially thought about compiling cc65 with cc65, however memory limitation is definitely going to be the tightest bottleneck, even with memory banking. (As I mentioned - in my case, even a bare minimum assembler that I wrote takes a lot of space, and I'm not yet even halfway through...)
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD
noneya
Posts: 39
Joined: 12 Feb 2021
Contact:

Re: 6502 assembler for 6502?

Post by noneya »

There is also Krusader and the A1 Assembler, those are the two I use on my hombrew's.

I like both of these. Both support lables.

I modified the A1 assembler a to add load and save commands, which work with my SD card solution. If you like it there is a nice sb assembler which is it's desktop version. With that desktop version you can choose to compile to many formats, binaries, hex, and so on.

You can read about / download the A1 Assembler here: https://www.sbprojects.net/projects/apple1/a1asm.php

I intend but have not yet modified Krusader for save and load, though it is do-able and one of my projects on the back burner.

Krudaser 1.3 has the support for 65c02 op-codes. Though it can be ran from ram, the choice to go with it's built in version of wozmon, which is only slightly modified is also a nice option as that route will have you set up for breaks right from the get go. You can pick up Krusader here - https://github.com/st3fan/krusader

Good luck
Shaking out the dirty bits!

https://github.com/DonaldMoran
fachat
Posts: 1124
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Re: 6502 assembler for 6502?

Post by fachat »

Here's also @ASS that I wrote originally for the C64, using its BASIC editor to do the actual editing and file handling (overlays do work though) http://www.6502.org/users/andre/misc/index.html

Edit: I bootstrapped it with a copied assembler I got somewhere, until it was able to assemble itself. It's 4k in size. It does not do CMOS opcodes, and is not really documented. So, just for reference
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Post Reply