Cross-assembler recomandations

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Cross-assembler recomandations

Post by Thowllly »

Hi, I'm new here, sorry if this has been discussed to death here before.

I'm looking for a 6502 (6510) cross-assembler for windows that can output .prg (c64) files and supports this sort of labels:

Code: Select all

-   [some code]
    ldx #7
-   [some more code]
    dex
    bne -       ;jumps back to previous -
    beq --      ;jumps back two minuses
Stupid example, the point is that I don't want to think up a new label name for every little branch.

Any suggestions for a good cross-assembler that does this?
Memblers
Posts: 64
Joined: 16 Jan 2003
Location: Indianapolis
Contact:

Post by Memblers »

CC65 supports it, but it can look a little messier at times. http://www.c65.org/

Code: Select all

  ldx #0
:
  dex
  bne :-  ; branch back
  dey
  bne :+  ; branch ahead
  (etc.)
:
X816 is another assembler that supports these generic labels (exactly like in your example), but it's old and for DOS and I've heard it doesn't work with newer versions of windows..
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

Thank you for your suggestions and quick reply.

I tried X816 but I couldn't get it to work under Windows, as you said, and it didn't seem to be able to output .prg files either.

CC65 looks good, I actually like its syntax better, but I'm not sure how to use it just as an assembler. My test file looks like this:

Code: Select all

:   clc
    bcc :-
It seems that the assembler can only output object files, not .prg files. Giving either the .o file or the asm file as a parameter to the linker it complains about an "Unresolved external '_main' referenced in: crt0.s(10)" (my file is not named crt0.s, infact that file is nowhere to be found)

Another problem is that I can't use *=$xxxx to specify the start address. The faq say I have to make a linker config file where I specify that, but I don't know how to make it or where to put it. I would prefer to be able to specify it in the asm file anyway.

If anybody has any suggestions on how to solve these problems or a suggestion for another assembler I would greatly appreciate it.
Memblers
Posts: 64
Joined: 16 Jan 2003
Location: Indianapolis
Contact:

Post by Memblers »

It sounds like it might be trying to compile it in C or use a library. I never use those features though (well, there's no official library for the NES, and I don't know C, heheh), so I only use ca65.exe to assemble and ld65.exe to link the objects.

One difference with ca65 compared to other assemblers is that you can't use .ORG in the usual way, or pad to a certain address. Instead you set up segments for the linker to use, and use .segment commands in the assembler to output stuff there. I believe there's a linker config for the C64 built-in, but you can make your own if you need to.

If that sounds useable for you, read the docs for ld65 and ca65. There's a lot of info in there.
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

Memblers wrote:
It sounds like it might be trying to compile it in C or use a library.
But why would it do that? I only do the following:
I have a file test.s containing two lines:

Code: Select all

:  clc
   bcc :-
On the command prompt I write:

ca65 test.s

It finishes without any output to the screen, but it generates a file test.o
I then write on the command promtpt

cl65 test.o

And it gives me the error message: Unresolved external '_main' referenced in: crt0.s(10)
If I try giving the asm file directly to the linker, like this:

cl65 test.s

I get exactly the same error.
I can't find the file crt0.s anywhere, maybe it's inside the c64.lib file or something, and that it expects a _main label or something, but adding a '_main' label it just complains about a missing ':', and adding '_main:' it still gives the same 'unresolved symbol _main' error.
Quote:
I never use those features though
And I don't want to use them either :)
Quote:
(well, there's no official library for the NES, and I don't know C, heheh), so I only use ca65.exe to assemble and ld65.exe to link the objects.
Could you show me the exact syntax you use to do that?
Quote:
One difference with ca65 compared to other assemblers is that you can't use .ORG in the usual way, or pad to a certain address. Instead you set up segments for the linker to use,
But do I need to use a segment for my small example?
Quote:
and use .segment commands in the assembler to output stuff there. I believe there's a linker config for the C64 built-in, but you can make your own if you need to.
My problem is, I don't have any idea how to make a linker config.
Quote:
If that sounds useable for you, read the docs for ld65 and ca65. There's a lot of info in there.
I did read the docs for ld65, but it only contained 7 almost empty pages, leaving me non the wiser. I've looked through the ca65 documentation quickly, I'm reading through it again more thoroughly now, but it's not of much help either. I just need a single example of code that can be compiled and linked directly and I can figure it out from there, but only code fragments are given.

My problem with the documentation is that it looks like it's written for somebody that allready knows how everything works. It's really frustrating.

I tried following the simple cc65 compiler intro doc, but it starts out by saying I should examine and understand the commands in the file "cc65setup.bat" in the samples/tutorial directory, but there is no .bat file there. The rest of the tutorial works though, but I still don't know whats wrong with my example.

Do you know if there exist any page with just a ca65 .s file ready to be assembled and linked I can look at?



UPDATE: I got it to work!:D

While writing this post I managed to get it to work. This file

Code: Select all

.export _main
.proc   _main
:     clc
      bcc :-
.endproc
seems to work. At 252 bytes it's a bit bloated, and I still don't understand how to specify where my code should go, but that's just details, I can worry about those later :)

I looked at the generated code with the monitor in the Vice emulator, and it's there, but it's surrounded by code that I don't know what does (except that it changes the font to the lower case one), but it's probably harmless and only adds one block to the file size, so I don't care (for now :))

There is 13 bytes of Basic code (to start the asm program), 85 bytes of unknown code, my program (3 bytes), and then some more unknown code. I'll take a closer look at it later.

Maybe I could somehow make it not target any platform, and append the bytes needed to make it a .prg file myself?

Thank you for your help, I greatly apreciated it.
Memblers
Posts: 64
Joined: 16 Jan 2003
Location: Indianapolis
Contact:

Post by Memblers »

Here's some code I'm working on:
http://mywebpages.comcast.net/memblers/nes2pc.zip
(it's named .PRG, but not for C64, just so you know)

Look at the n.bat to see how it goes together. I think using a custom linker config (the -C option) is the same as targeting no platform in particular, just a custom one. nes.cfg is what I'm using.

All the details about the linker config will be found here:
http://www.cc65.org/doc/ld65.html
But yeah, it is kinda confusing. I've been using it for a few years, and I'm still not totally sure how everything works, heheh.
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Post by 8BIT »

Thowllly wrote:
I can't find the file crt0.s
The crt0.s file is in the source code for the CC65 package. Each target system has a unique file. This code sets up the target system's memory for the C libraries. It copies some zeropage locations to a temp storage area, inits its own variables, invokes the user program (_main), then restores the zeropage locations before exiting.
Quote:
I looked at the generated code with the monitor in the Vice emulator, and it's there, but it's surrounded by code that I don't know what does (except that it changes the font to the lower case one), but it's probably harmless and only adds one block to the file size, so I don't care (for now :))

There is 13 bytes of Basic code (to start the asm program), 85 bytes of unknown code, my program (3 bytes), and then some more unknown code. I'll take a closer look at it later.
Again, thats the crt0.s code sitting in front of and behind your code.
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

Memblers
Thank you for those files, they were exactly what I needed! I've looked at them, I think I understand how it works now.


8BIT
ok, I thought it was something like that. Quite usefull, I'm sure, but I think I'll do without it. I'll just use the old fashioned way of reseting the machine to exit my programs :P
BoneSmoke
Posts: 4
Joined: 10 Jul 2003

Post by BoneSmoke »

I'm not sure wether you're looking for a cross assembler or cross - compiler ...

CC65 is a small C cross-compiler it works really well with the Bloodshed Dev c++ IDE

Relaunch64 is a really good cross assembler IDE .. ( http://www.koolpeople.de/tools/r64-german.zip ) I was using it with the ACME assembler , but switched over to c64ASM..
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

BoneSmoke wrote:
I'm not sure wether you're looking for a cross assembler or cross - compiler ...
I'm looking for a cross-assembler that supports unnamed labels.
Quote:
CC65 is a small C cross-compiler it works really well with the Bloodshed Dev c++ IDE

Relaunch64 is a really good cross assembler IDE .. ( http://www.koolpeople.de/tools/r64-german.zip ) I was using it with the ACME assembler , but switched over to c64ASM..
Relaunch looks really cool, but I don't read german...

I tried ACME and c64ASM, but as far as I can see they don't support unnamed labels.

I'm very surprised that unnamed labels seems to be such a rare feature. Requiring the user to name every label is like a higher language requiring you to name every {...} block. Very strange, I think...
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Post by GARTHWILSON »

I've never heard of an assembler that didn't need labels to calculate branch operands. To quickly make up labels that won't be repeats of those in other routines, I just take two or three letters from the routine name and add digits to the end and a dollar sign meaning that it's only of local interest. For example, branching down four lines in a routine called "CREATE_FILE", the instruction might read BEQ cf3$, and the cf3$: label would be indented one space from the edge so the "condensed display" feature of the text editor would not show it when it shows the major labels like CREATE_FILE:

To do your branching and program structures with any macroassembler, perhaps you should use macros. You could even put in error checking to catch things like "UNTIL" without the corresponding "BEGIN" for a BEGIN-UNTIL loop (using Forth-like structure words in this example). This would make your code a lot more structured and clear, and essentially elevate the level of the language.
orac
Posts: 64
Joined: 31 Aug 2002
Location: USA

Post by orac »

Hi Everyone,

A discussion about 6502 X-assemblers would not be complete without a mention of 65CM.

http://hem.bredband.net/b129764/Siders/

Cheers,

Paul
John West
Posts: 383
Joined: 03 Sep 2002

Re: Cross-assembler recomandations

Post by John West »

Thowllly wrote:

Code: Select all

-   [some code]
    ldx #7
-   [some more code]
    dex
    bne -       ;jumps back to previous -
    beq --      ;jumps back two minuses
In my opinion, this kind of syntax is the work of the devil. Any assembler that supports it should be burned. What happens when you decide to add a loop or branch to [some more code]?

The best that I've found is local labels. You can do them by hand, like Garth's suggestion, or you can use an assembler that supports them. I don't know any 6502 assemblers that do, but assemblers aren't that hard to write, are they? :-)

Code: Select all

CREATE_FILE:
        (some code)
    1$:
        ldx #7
    inner_loop$:
        (some more code)
        dex
        bne inner_loop$
        beq 2$
Use a proper label only at the start of each subroutine. Within the subroutine use local labels. You can use meaningful names without worrying that they're used in other subroutines, or numbers. I also use the indenting style that Garth suggests.
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

Hi all!

Thanks for the new suggestions since my last post.

I decided to write my own x-assembler, and today I finally did it! I wrote it in Java and as JW said it wasn't very hard to write. It's very basic at the moment, but it works.

But for now it only outputs binaries. I would like it to output .prg files but I don't know how the header is supposed to look like. I believe that for real .prg on a c64 disk the only header information is two bytes specifying where to load the program to. But the .prg file format used by emulators seems to have a bigger header.

So, my question is: Do anybody know the exact specifications for the header for .prg files?
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

I think I must have gotten .prg files and .p00 files mixed up or something, because today I looked at some files I had assembled earlier with A6, and they only had the expceted 2 byte start address header.

I added the start address to the output part of my assembler and tried assembling a 5k .asm file I had allready assembled earlier with A6. My assembler produced an identical file (but with a different filename just to be sure I was looking at the right file) to the one made by A6, and it worked in WinVICE.

So, now I'm very happy, and hopefully I won't have to bother you again with any more stupid questions :)
Post Reply