6502 discussion on Hacker News

As of writing, there’s an article on the educational merits of the 6502 featured on the Hacker News frontpage: “6502 is a Good Starting Point for Beginning Assembly Programming”, by Emanja Trifunovic.

The related discussion may be interesting (not so much in favor of the 6502, as far as I can see):

3 Likes

It feels to me there’s scope for several kinds of reasons for having assembly language in a course. One is because it is inherently a good idea to program at low level to help bridge the gap between logic and software. One is because your students might want to get paid to do low level coding. One is because you want to teach computation from bottom to top, in a Nand2Tetris kind of way.

For the first, you might pick a sensible historical example - a slightly more obscure choice might be some defence against cheating. A popular CPU might have useful minimal portable open source emulators available.

For the second, you might pick some industry standard 8 bit machine.

For the third, you might want something regular with HLL support.

I would be entirely unsurprised if some courses are built around 6502 because it’s teacher’s favourite micro!

Of course, I approve of the choice of 6502, for personal reasons!
Musings on my fondness for the 6502

3 Likes

I like the 6502 for its simplicity, as well. However, its extremely limited number of data registers makes it a challenge to juggle data for computations. I’ve found that I have to plan them out for anything remotely complex.

The first assembly language I learned was on the 68000, when I was a sophomore in college. I think it has a very well designed instruction set. I also think it’s easy to learn. The number of registers makes it easy to set up computations. Unlike the 6502, its instruction set is flexible re. how you arrange your computations. As I recall, you can grab operands from addresses, or registers, or both. It doesn’t care. I liked it a lot. It really helped me drop my fear of assembly programming.

The 6502 instruction set is designed such that computations are set up along a “track.” You can’t just say, “I want to add operands from these two addresses, and put the result in the Accumulator.” There’s really only one way to use the CPU’s “add” and “subract” instructions: One of the operands must be loaded into the Accumulator. The other operand must be referenced in the arithmetic instruction (a literal, or from an address).

The other two data registers, X and Y, are special-purpose. They can be used to store values, but you can’t do the same things with them as the Accumulator. They’re designed as index registers.

A technique I’ve tended to see is 6502 programmers using the processor stack to hold extra values that they’re “holding in reserve” for a computation, rather than using X and Y, because you don’t run out of “slots” to store things. Whereas, on the 68000, which has a processor stack, I didn’t find it necessary to do that often, since you have a large number of registers, which can all be used the same way (except for a7, which is the stack pointer).

To me, the 6502 takes more thought to use than the 68000, because you have to manage a very limited resource. The instruction set is not very flexible. it tends to give you only one way to do different things. I found with the 68000, it let me decide how I wanted to arrange data values, and how I wanted to include them in computations. That felt nicer. Though, I still find dealing with the 6502 fun, because of its simplicity.

2 Likes

I think it helps to see the 6502 as an accumulator machine with index registers. It’s not quite that, but it’s pretty much necessary to use main memory for most work. The zero page addressing makes that relatively fast and compact, and in fact the indirection modes mandate that pointers are (at least temporarily) in zero page.

So there’s lots of efficient idiomatic hand-written code which uses those facilities well.

What doesn’t work so well is most compilers, or people who’ve got habits based on register files and haven’t yet learnt the local idiom. In particular the stack is mostly only useful as a return stack - it’s not well-used for parameter passing. It can be handy for temporary storage, but so is zero page.

What the 6502 programmer does have to do, for efficient idiomatic code, is allocate their usage of zero page carefully. On some 6502 platforms, half of it is for the OS and half for applications. On others, it’s more of a challenge.

1 Like

In this context, it may be interesting to consider the kind of conceptional journey that already preceded the 6502, namely, the initial ideas for the Motorola 6800. Here’s Jeff LaVell in the CHM oral history interview with the 6800 team:

We also, that was the time of the PDP11, and it was the great hi-technology computer at that time, so a little mini-thing with a lot of switches and so that was a neat architecture and we liked that a lot. So we started with that architecture and built some variations on
it, and the original product definition of the 6800 family was a 16-bit machine. And then we talked to Tom and he said, “Go away.” And then we evolved into the real world of what we could build.

https://www.computerhistory.org/collections/catalog/102702020

It seems, the 68000 is more like the kind of the 6800, the team originally wanted, (but with even wider registers) and the 6800 is the result of these ideas interfacing with reality. (I.e., the reality of microprocessor production of the time.) With the 6502, there’s another step in reduction, which made the processor more similar to PDP-1 than the PDP-11 (especially, because there’s now just a single accumulator), more RISC-y, but also more rigorous.

This makes it in my opinion a good second language to learn, since it teaches you to manage with the resources available and to lay out your algorithms and control flow accordingly. Which only makes sense, if you’re already familiar with the major principles of programming. And it’s great for recreational programming, since we love to bang our heads against walls to achieve, what may not be as easy at it may appear to be at first glance.

2 Likes

Since this post seems to have drifted from “Educational Merits” to what I sense is the aesthetics of efficiency and ‘bang head against wall’ challenge, I’d like to throw the RCA 1802 into the ring. To say programming anything of interest is a challenge with this weird ISA would be an understatement. The 16, 16-bit registers cannot be used for logic or arithmetic, only pointing, indexing, and temporary storage. Memory access is strictly register indirect, with immediate literals being the only direct memory addressing mode for data. Branching is absolute, but relative addressing can be done inefficiently with a bit of math and poking the low byte of the current ‘P’ pointer register. Planning ahead is quite the necessity since the 16, 16-bit registers get used up quickly. Auto-indexing for stack operations consists of only post increment and decrement, so not like a conventional SP operation.

There is no conventional subroutine branch and return, just the ability to change the ‘P’ register pointer (acts as Program Counter) with the SEP (Set P) instruction. I refuse to use the SCRT - “Standard Call and Return Technique”, an unbelievable amount of code to do what most other normal microprocessors do with two simple instructions. SEP-ing is nice for very short programs but becomes a logjam when the program grows. I tend to use self-modifying code by jamming a return SEP onto a designated Return Stack and doing a return via an (indirect) SEP to the return stack. The joys of ram-based von Neumann machines! Lots of silly tricks to invent here.
Anyway, for sheer joy, frustration, and challenge with an instruction set that can be easily memorized for hand assembly, give the 1802 a try. You’ll learn more about yourself than computing with this little beast.

3 Likes

It (1802) was good for bread boarding, as it had a bootstrap feature.
Getting back to the 6502, it was 5 volts and easy to clock for bread board
computing.
I favor the PDP 8 for beginning programing for the reason it is so simple.
and IO is well defined. If you need to code more than a page, time to learn
on a bigger machine. (The bigger machine is being built as we speak)
Ben.

There’s another way I was sort of thinking of a way to think about the 6502 (if that makes sense) and that’s as a micro engine for a more complex machine.

So using native 6502 assembler as a “microcode” for a system that has a 256 byte register file where ‘registers’ can be variable numbers of bytes or a 2-byte pointer then you end up writing short segments of code to manipulate these meta registers.

This is of-course how we use zero-page in the 6502 - by writing short snippets of code to (e.g.) do arithmetic on these ‘registers’ and move the register contents to/from main store.

But that just ends up being “normal” 6502 code so maybe it’s not a good way, but I felt that was what I was doing writing a bytecode interpreter and for my other project (a TinyBasic interpreter).

Maybe the 6502 just lends itself to that sort of thing by accident - starting with Sweet-16 for example…

-Gordon

1 Like

In a similar vein, I was musing that perhaps the 6502 way is more like Fortran whereas the 68k way is more like C. In Fortran you manage your own storage, you might have Common blocks to arrange for (sub)programs to share memory locations.

1 Like

Does the 6800 belong to LISP programing. You have it all covered. :slight_smile:
I think more of FIG-FORTH for the 6502. Virtual machines really seemed to pop up
after the Apple ][ came out and before the CP/M card.

I don’t think any of the 8-bit processors of the 70s are a natural fit for high-level languages, and that is part of the appeal for me, at least.

That said, there was a Lisp implementation for the 6502, and an APL implementation for the 8080, as well as a number of other languages, so clearly not impossible… but also, clearly, not all that practical.

1 Like

Maybe the 6502 is not a natural fit, but if someone implements a language for it, that seems fine to me! Acornsoft did exactly that, producing a BCPL, Lisp, Forth, Comal, Logo, Prolog, Pascal… in other words, the mismatch is a problem for the implementer, not for the user, ideally. A shortage of RAM might always be a difficulty.

From the CCH website:

3 Likes

You can make a compiler generate fast 6502, if you cheat a bit.

2 Likes

Only rather recently I came across a “middle level programming language” which aims to be good for both implementors and users, on 6502 and on Z80:

I dare say it’s one of many not-quite-C designs.

3 Likes