-1

6502 assembly is a language meant for humans to compile it themselves, not compilers. Its an older Assembly that powered the olden days of computing and consoles such as the NES and Atari 2600. I want to make an executable file that you can download and run without any other software. In short, all I want to know is:

  • Can I compile 6502 assembly into a stand alone application, preferably for Windows?
  • 3
    Sorry, dunderhead question probably: by "meant for humans to compile it themselves" you presumably mean write it themselves directly at the assembly level? 99% of 6502 work will have been done with an assembler actually turning the opcodes into bytes. – Tommy Jan 23 at 16:40
  • 2
    You have written Assembly 6502 in italics as if it is a reference to a specific thing i.e. an article, book, program etc., but I searched for that and saw no obvious result. Are you just referring to what is more commonly called 6502 assembly? If not, please provide a link. If you are referring to 6502 assembly, then technically, no you cannot compile it to a stand alone application, but rather you assemble it into a stand alone application. – Glen Yates Jan 23 at 16:56
  • 1
    @GlenYates I'm the source of the italics (which is kind of funny, because I answered a question recently on ux.stackexchange.com about italics, but I digress). I put it in italics based on my understanding of "a reference to a specific thing" but I agree that the normal sense would be more generically "6502 assembly" using any standard assembler. – manassehkatz Jan 23 at 17:09
  • 1
    If your target platform is PC/Windows, why don't you use x86 assembly ? (It's almost as old as 6502) – Bregalad Jan 24 at 10:08
9

It's a classic Yes, but... situation, not least due to the fact that the question is way too broad/unspecific. An environment isn't just a CPU with a certain instruction set, but a whole machine defined by its interfacing capabilities and more often than not even its timing characteristics.

Let's start with the CPU. There are at least three major ways to do this (and many in between):

  • Bundle the 6502 code with a Windows executable interpreter that handles it as a bytecode, following the execution path.

    That's the most simple way and will generate the highest compatibility (if done right). At the same time, it will be comparably slow - not that this would matter in real life situations where the Windows machine will be several orders of magnitude faster than any real 6502 from back in the day.

  • Compile the 6502 source code using an assembler outputting x86 code matching the 6502 functionality. With the right wrapper for initialisation and exit, this code could be directly executed under Windows.

    Again not a big deal to do so. It also (might) produce the fastest possible x86 code to perform. But there are many issues to circumvent, even before it comes to self-modifying code. Not least may be different code length and address usage. With self-modifying code, this approach is impossible as there is no active component turning such changes into modified x86 code.

  • Last would be a just-in-time compiler. Somewhat of a middle way between the first two. Here as well an interpreter handles the 6502 code, but in addition to executing each statement, they are also grouped into linear code chunks, translated into x86 and put in a side cache. When the code gets executed a second time the precompiled x86 code gets run from the side cache instead. Since there is still the original memory/code image, every 'tricky' way, including self-modifying code can be detected and handled accordingly. Like with the interpreter solution this could be packaged with your 6502 code as a windows application.

    This approach is much like Transmeta used for its Crusoe processors. In general, it will result in great speed enhancements compared to interpreted code, and due to the rearrangement maybe even faster (*1). The downside is the need for quite a complex tool.

So far, this is solvable. But what makes an answer hard is that there is no hint about what system the hypothetical 6502 is embedded in. After all, without I/O such a CPU is like a silenced blind man in an iron maiden. All it can do is bleed electricity :>))

So either you

  • have a certain existing 6502 in mind, then the solution is to take a fitting emulator for that machine for Windows, and maybe package it with some script to load and start your code at startup.

Or you want to

  • do 6502 programming in Windows. In this case, you need either of the above solutions and create in addition an interface to call Windows functionality from within the 6502 code. At least that would require a way to transfer buffers for call information and in-/output data from the 6502 side to the interface code. Again, not a big deal, but a lot of work.

In any case, it might be helpful to get a bit more insight what your question is really about.


*1 - One of the interesting results of Transmetas research was that even code translation into the same CPU (read x86 to x86) may result in considerable speed up.

  • Interesting - do you have a reference on the x86-x86 translation result? – Thorbjørn Ravn Andersen Jan 24 at 16:50
  • It came up during a chat with one of the Transmeta core developers at VCF in California, IIRC in 2004 or 2005. – Raffzahn Jan 24 at 22:28
4

In theory, yes. You can translate anything in anything else. In practice, it's hard to do -- the plain assembly language (like any assembly language) only knows instructions that do one of four things or a combination of them:

  • arithmetic operations
  • read a memory cell
  • write a memory cell
  • check and/or modify some internal CPU state (this includes jumping)

But any meaningful program will also do some I/O ... and the CPU (which defines this language) has no idea about that. So, the way this is done depends on the concrete target system as a whole, e.g. on a C64, you would program the VIC-II chip for screen output. A "translator" would have to understand what these register accesses etc mean in order to create e.g. a windows program from your assembly source.

Anyways, such a thing was attempted for the NES: https://andrewkelley.me/post/jamulator.html

In this case, the input was the machine code, which creates additional problems: you must first understand what is really code and what is just data. If your input is assembly source instead, I'm pretty sure it can be done (given you know the exact target system) -- but it's definitely not simple.

3

As with so many things, maybe. Assuming that "Assembly 6502" is a full 6502-compatible assembly language:

  • If you assemble an entire bootable image and burn it into an EPROM (or equivalent) and install that in a 6502-based system, then the answer is yes. The typical alternative would be to assemble just an application and then run that (via ROM cartridge, disk, load from tape, etc.) using whatever operating system exists on the 6502 system, but technically that would use "other software" as operating systems are "software".
  • You can't make a fully executable program file for Windows, simply because Windows doesn't run on a 6502 CPU and the program needs to be compatible with the CPU. You could run it in an emulator of some sort that is running as an application inside Windows, but then it is most definitely not "without any other software"
  • Did you mean "6520-based system"? I know that lots of Intel chips were labelled "xyzn" -> "xynz" -> "xnyz" but I don't know if this is one of them. – wizzwizz4 Jan 23 at 18:23
  • No, that was just a typo. Fixed. – manassehkatz Jan 23 at 18:26
  • 1
    I like the 'Maybe' part :))) – Raffzahn Jan 23 at 19:03
  • 2
    I would consider embedding an emulator into the executable a form of "making a fully executable program file for windows". The only issue is that the executable will probably be more bloated than you'd perhaps want it to be. Such an executable would require no other software to run. – secondperson Jan 23 at 22:16
2

6502 assembly is a language meant for humans to compile it themselves, not compilers.

"Assembly language" is not compiled. It's assembled by a program called an assembler.

Consider the following simple 6502 assembly program which, on a Commodore 64, will print the string "HELLO WORLD."

        LDY #$00
LOOP    LDA STRING,Y
        BEQ EXIT
        JSR $FFD2
        INY
        JMP LOOP
EXIT    RTS
STRING  .DB 'HELLO WORLD'
        .DB 0

Above, you have instructions (e.g. LDY - load Y) and the operand to that instruction (#0). The operand also expresses the addressing mode, which is "how" the instruction is supposed to get its data.

#$00 means immediate - which means we want to load Y with the literal number 0 and not what is at address $00.

STRING,Y is Y-indexed - this means we want the value at address STRING plus Y.

Each instruction + addressing mode combination results in a unique 1-byte opcode. Opcode list is here.

So you can see from the following excerpt from that site what the assembler does:

Absolute,X    LDA $4400,X   $BD  3   4+
Absolute,Y    LDA $4400,Y   $B9  3   4+

The assembler will take the text "LDA $4400,X" and generate the 3 byte sequence BD 00 44. 6502 consumes its addresses in the instruction stream in low-byte, high-byte order.

Going back to my example program, the assembler would take the line "JSR $FFD2" and at that point output the 3 byte sequence 20 D2 FF.

Can you take the opcode table, look up each opcode in your program yourself, and manually specify the byte stream? Sure. I believe this is what Wozniak did when developing Integer BASIC for the Apple in the 70's. Bill Gates probably did this do for the first BASICs he wrote at that time as well. This is what it means to assemble a program yourself.

You noticed in the short program I wrote that I used labels. This is one of the higher-level things a good assembler does - it goes through the program in 2 passes and inserts/resolves addresses (somewhat like a linker), and this allows you to use labels and it will figure out the addresses.

Compilers will take higher-level constructions like if statements and mathematical expressions, and generate complex sequences of opcodes (or assembler text to be later processed by an assembler) . An assembler is merely translating mnenomics to opcodes and possibly supporting some very simple math like adding two labels or a label and constant together.

Of course some assemblers have macros and a sophisticated preprocessor that blurs the line between assembler and compiler.

So:

Can I compile 6502 assembly into a stand alone application, preferably for Windows?

Obviously a raw 6502 bytestream will not be understood by x86 CPU, and you noticed in my example Commodore 64 program, I used a JSR $FFD2. This is a ROM routine available only on the Commodore 64 platform. It won't exist on any PC-compatible system. The ROM routine also creates text by writing to "screen memory" - the area of memory $0400-$07FF which the VIC chip reads to generate a display. This VIC chip also doesn't exist on any PC-compatible system.

Emulators can help, of course. There are many 6502 emulators that could be included with 6502 code bytestreams to form a standalone executable. Nothing really stopping anyone from doing that.

But including an emulator as part of an executable - this doesn't solve the problem of how you get 6502 code to perform I/O. You'd have to define a "virtual hardware" platform and also have code that bridges between that virtual platform and the operating system to produce graphical or text out.

UNIX-style text-based terminal I/O would not be too difficult, but something like outputting to Windows forms or interacting with Windows graphics subsystems in a meaningful manner would require more work. And that means the 6502 code you write will only work for this virtual platform.

  • An assembler is a compiler - it takes source code in and generates machine code out. – Thorbjørn Ravn Andersen Jan 24 at 16:51
  • There's a difference between assembling and compiling. While they both generate source code they don't do it in the same way. – LawrenceC Jan 24 at 16:54
  • 1
    An assembler is a compiler in the same sense that you can say all integers are real numbers. While technically true it is usually not useful. There are many techniques that are useful to compiler writers that make little or no sense for an assembler, especially an assembler for a very primitive CPU such as the 6502. – Ken Gober Jan 24 at 17:47
1

I suspect that the question asker may not have fully understood what "6502 assembly" actually is.

Processors execute "machine code", instructions prepared for them to execute. One of the ways to create machine code is to use "assembler," a type of very simple programming language which is easier for humans to read, write and understand than actual machine code, but is also much easier to translate into machine code than a high-level language such as C++, Basic, or Python.

Because assembler source code is easy to translate into machine code, it is specific to a particular kind or family of processors. This is because different families of processors have different sets of registers, different addressing modes, and are generally programmed in different ways. Humans have been designing processors since the mid-1940s, but that field of engineering is still making progress, and there are almost certainly better ways to do it than anything in use now.

Translating assembler code for one processor into assembler code or machine code for a different processor is unusual, and normally only done when the two processors are related, but not actually compatible. Trying to do it in a general case is rather hard, and it is usually better to have a human re-write the code in a higher level language.

"6502 Assembler" is assembler source code for the MOS Technology 6502 family of processors, including the 6502, 6501, 6507, and later derivatives by other companies. These processors were used in lots of micro-computers, games consoles, and other devices from the mid-1970s to the mid-1980s. Nowadays, they are used in small-scale embedded systems, but definitely not in any computers that can run Microsoft Windows.

This is because a 6502 processor can only handle 64KB of memory at a time, which is definitely not enough for even the earliest and simplest versions of Windows, lets along the much bigger modern ones. So you cannot run 6502 machine code directly on any Windows machine, because the processor(s) in the Windows machine can't understand 6502 machine code.

There is a 6502-derived processor design, the 65GZ032, that might theoretically be capable of running Windows, were Microsoft motivated to produce Windows for it. However, it is slow enough and obscure enough that this is never going to happen.

If you want to learn to program in 6502 assembler, it's time to consider why you want to do this. If it is to write games, or other software, for 6502-based machines, you'll need a real machine to get the timing and gameplay right, and using that will be the easiest way to do development. If it's for some other reason, please edit that into your question, and we can try to answer it.

0

This question is problematic because it's poorly phrased, so that the technically correct answer is "yes" while the answer to the question really being asked is "no".

No, you can't compile 6502 assembly into a standalone Windows application. Windows only runs on a certain set of processors, and the 6502 is not included in that list. If there is no version of Windows for the 6502, then naturally there can be no Windows Applications for the 6502 (ignore the idea of emulators for now, we will come to that later).

So, if you can't do this for Windows, how about another system that does support the 6502? Let's use the Commodore 64 as an example of a 6502 system. In this case the answer is "yes", but we don't typically call this "compiling", we call it "assembling" and the program we use is called an "assembler". An assembler converts assembly language source code into machine code, via a straightforward mapping of opcode mnemonic names into numeric values (plus other details not important for this question). This is easy to do because the assembly language for the 6502 is designed to be converted to 6502 machine code, in such a straightforward way that you could do it by hand using pencil and paper if you did not have access to an assembler.

But there's more involved here than just translating assembly language into machine code, you need to take that machine code and put it in a file that can be run as an application. How exactly this is done depends on the specific computer that's going to be running the code. This means, an assembler for a Commodore 64 will produce different output than an assembler for an Apple //e or an Atari 800 (or an NES console), because the different computers have different file formats and loading conventions even though they all use the same 6502 processor (or close enough to the same as far as this question is concerned).

So if you have a Commodore 64 assembler, then yes it can produce an executable program that will run on a Commodore 64. Likewise for an Apple //e assembler, it can produce Apple executables, and an Atari 800 assembler can produce Atari executables. I am ignoring the idea of "linkers" or "loaders" here to keep things simple; for the purposes of this question just pretend that linkers are always built into the assembler.

This means, if you want to assemble 6502 assembly language into an executable program, then you need an assembler that will produce an executable file in the correct format for whatever computer you plan to run the program on. Normally this will always be a 6502 based system because it would be a ridiculous waste of time to try to write programs intended to run on an x86 PC using 6502 assembly language. Instead, you would use x86 assembly language to write x86 programs, or you would use a higher-level compiled or interpreted language such as C, Pascal, BASIC, etc. Since there are no native assemblers that will convert 6502 assembly language to x86 machine code, again the answer here is "no".

But "ridiculous waste of time" is not the same thing as "not possible". It is in fact possible, and the way you would do it is by writing an emulator that simulates some 6502-based computer (including simulating its input and output devices because without input and output programs would be useless). You would then "load" your 6502 executable within this simulated computer, and the simulated computer would "run" your code and things would happen. So the answer might be "yes" except that there's no single-step "compiler" that will take 6502 assembly language and produce an x86 program that includes both your program and a simulated system to run your program in, all in one step. You can achieve the outcome of a runnable application that includes everything, but it's a multi-step process and requires more than just a compiler, and the details of how to do it are really too much for a Retrocomputing SE question to answer.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.