6502 Is a Good Starting Point for Beginning Assembly Programming
50 comments
·February 6, 2025kazinator
musicale
> The best way to learn how to hack around the limitations of a tiny machine is to completely ignore them and become a seasoned software engineer
Learning to hack around the limitations of a tiny machine is a good step toward becoming a seasoned software (and possibly hardware) engineer!
The advantage of tiny systems is that you can understand them completely, from silicon to OS to software.
The 6809 is simpler than the 68K, and more powerful and orthogonal than the 6502, but there isn't the same software base for it. I think Motorola was onto something with the 6809 and 68K instruction sets and programmer-facing architecture. IIRC PDP-11/VAX and NS32K are similarly orthogonal.
mikepavone
Yeah. If you want to teach someone to implement a CPU, then the sort of simplicity the 6502 brings to the table is useful, but it's definitely not the most straightforward CPU to write code for.
The 68000 instruction set is very C-like (probably because it draws a lot of inspiration from the PDP-11 which was C's first target). Implementing it sucks (I know from experience) because the ISA is on the large side and all the little pragmatic exceptions add up. But because these exceptions are fairly pragmatic, they're not really a big issue when writing code.
KingOfCoders
68000 is much more pleasent from my experience (~40 years ago, so might be wrong). Personally I also like the Z80 better than the 6502, but that is just taste. The biggest benefit of the 6502 was a zero page, I loved the idea. My favorite computer book of all time is "Z80 Assembly Language Subroutines".
serviceberry
I really don't see how. When students are first exposed to computer programming, it might make sense to start with toy / compact languages that don't have any real-world use. But assembly is not the first language you're supposed to learn!
It's very utilitarian and most commonly just used for debugging and reverse engineering. So why would you waste time on the assembly language of a long-obsolete platform?
Plus, the best way to learn assembly is to experiment. Write some code in your favorite language and look at the intermediate assembler output, or peek under the hood with objdump or gdb. Try to make changes and see what happens. Yes, you can do that with an emulator of a vintage computer, but it's going to be harder. You need to learn the architecture of that computer, including all the hardware and ROM facilities the assembly is interacting with to do something as simple as putting text on the screen... and none of this is going to be even remotely applicable to Linux (or Windows) on x86-64.
scarface_74
I started programming in AppleSoft BASIC in 1986. But quickly became fascinated with 65C02 assembly. By the time I got to college and started taking different programming language classes, I quickly fell in love C. My knowing assembly helped me understand C and even though I haven’t learned any other assembly language since then, when I read articles about low level architecture of processors, I can follow along.
Let me take that back, I did learn 16 bit x86 assembly and the int21 DOS commands in college.
chasil
In many decades past, there were no high level languages, and assembly was the only language.
It was a very different time. Those people would be equally astonished at our casual computing devices and ignorance at how they work.
Oddly enough, my current karma score is 6502. Synchronicity indeed.
kazinator
The era in which there was nothing but assembly language was very short-lived.
By the time the 1950s were over, we had higher level languages.
Like before The Beatles recorded their first album.
musicale
6502-based microcomputers like the Apple II shipped with BASIC and a 6502 monitor.
The reason is that BASIC and low-level monitors can fit into tiny amounts of memory.
leptons
I went from BASIC straight to Assembly. I wish they had taught me Assembly when I was 9 years old (in the 1970s) instead of BASIC. Once I learned Assembly I never used BASIC again.
progmetaldev
Can anyone speak on how it is to move from an older assembly, to a modern CPU? I asked to take an assembly class in local/public college, and was told they wouldn't hold the class because not enough students were interested. This was in 1998, and I truly couldn't believe my ears.
I feel like learning modern assembly would be more useful, but maybe 6502 assembly is far easier to pick up? The first language I learned was Atari BASIC around 1991, and it was enough to get me to keep on moving to better languages and more powerful CPUs, but I wonder where I would have ended up if I learned assembly either before or after Atari BASIC. I try to keep up with technology, and have read quite a bit on different assembly dialects. I still haven't learned an assembly that I can program in, and I suppose it's because there are so many other high-level languages now and I feel like I need to keep up to what is used in "industry" rather than what is more obscure (but might help in debugging).
kiwih
I noted in a different comment in this thread that we teach all first-year compsci and software engineering students at my university MIPS assembly. They may then specialise into other areas, security, operating systems, embedded, etc., and in those specialties may need assembly for more modern CPUs.
We have found that when needed, students pick up the newer/more advanced assembly languages (e.g. ARM, x86) fairly well, so we believe the early and universal introduction to MIPS does provide benefits.
classichasclass
I moved from 6502 assembly to PowerPC assembly. I found 6502 assembly easy to understand because of the limited number of registers, instructions and addressing modes. You didn't have to learn very many.
And as it turned out, I didn't have any problems adapting to the expanded PPC ISA. Being on the 6502 already taught me how to chop problems down into tiny bits and now the bits didn't have to be so tiny. I certainly wasn't trying to do 8-bit chained adds for bigger quantities anymore; it didn't make sense to when I had 32-bit registers and an FPU.
__alexander
Check out Assembly Language for x86 Processors by Kip Irvine. It’s probably one of the best books on x86. The older editions are way cheaper.
adiabatichottub
One thing to consider is that there's a whole world of 8, 16, and 32-bit microcontrollers out there being used in new products every day. They are all readily programmable in assembly language, and if you have the basics down then the learning curve isn't terribly steep.
leptons
I started with BASIC on a Vic 20 in 1979 in a computer class for kids. Then I got my own Atari 400 at home, so I learned BASIC on that. Then around 1984 I got a Commodore 64 and it was amazing. I quickly got past the BASIC part of the C64 manual and in the back of the manual they had a memory map, all the hardware registers for all the chips, and then all the 6502/6510 opcodes. There was even an entire schematic for the C64 in the back of the book as a fold-out poster. 14 year old me was hooked. I got into assembly when I was about 15 and never looked back to BASIC. I wrote a lot of assembly code for many years, creating "crack intros" for cracking groups and demos on the C64. I then moved on to Amiga and 68000 assembly, and I even got into SNES 65C816 (16 bit version of 6502) assembly coding using a 30th generation photocopy of the pirated SNES developer manual and a floppy disk game copier, which also had a parallel port that I managed to connect to my Amiga and use that as the development system uploading the compiled program to the SNES via parallel port. I would make "crack intros" for SNES games being traded on pirate BBS's. It was a lot of fun. Many years later, I'm still doing some 8-bit assembly code for microcontroller projects where I'm trying to use the smallest possible CPU to do interesting things. Everything I learned about Assembly on the C64 still applies to the modern microcontrollers (PIC/AVR) that I use today.
In so many of these years I had not learned C. I went from assembly to scripting languages, and was a very early adopter of Javascript since the same month it first came out. Only in the last 10 years have I learned C, and it was so easy! After learning Assembly and Javascript, C was right in the middle.
I've programmed in over a dozen languages through the years, but I'm really happy with Assembly, C, and Javascript as my stack depending on the project.
progmetaldev
Thank you for this, I was born in 1979, but got introduced to the Atari 8-bit computers VERY early, and connected immediately. I have a Raspberry Pi v4, and it sounds like learning assembly on nearly anything right now will pay off. I don't have a problem learning a new language, but the C-style of languages are easiest for me. I'm sure them being imperative is a huge plus for me learning new things about any imperative language. I actually find JavaScript to be quite satisfying to write code in, mostly because I can test out functional features more easily than adopting an entirely different language to do it in.
I spent my teenage years grabbing cracks and texts from BBS', and enjoyed the whole scene. It's really what sparked my interest into writing software, and I always wished I had learned some lower-level skills beyond running a debugger and poking at memory. I felt like if I knew Assembly, I could get into deeper debugging (cracking was initially my "exciting" topic to cover, but now I feel like it would just be understanding memory better when I run into a strange error).
Findecanor
6502 is a bit limited, so you'd have to resort to self-modifying code to get things done — and self-modifying code is a big no-no on any processor with cache, and therefore not a good habit to acquire.
For teaching, I would instead go with RISC-V. In particular RISC-V with the bitmanip extensions, which make some things much easier and gives it feature-parity with the base set on x86 and ARM. The Raspberry Pico 2 has two RISC-V CPUs with those. The board is easy to use, widely available and has a lot of support. There are also alternative boards with the same MCU but other form factors and features.
hippospark
I prefer RISCV as an starting assembly language because: it has good design, it's more intuitive, it has modern language and tool support (GCC, LLVM, Rust, etc.), and it runs on QEMU and real available hardware.
musicale
> real available hardware
Last I checked the 65C02 was still being manufactured and sold.
It can also at a blazing 14 MHz.
brucehoult
It's $8 and can't run without external ROM and RAM and a clock circuit and some glue logic.
A RISC-V CH32V003 32 bit processor with 2k RAM and 16k of flash running at 48 MHz costs $0.10 for an 8 pin package (6 available I/O pins) or $0.20 for the 20 pin package. Once programmed, it needs only electricity between 2.8V and 5.5V to be applied to start running.
https://www.aliexpress.com/item/1005005036714708.html
You can get it on a ready-made board or kit for as little as $1.
https://www.youtube.com/watch?v=dfXWs4CJuY0
https://www.olimex.com/Products/Retro-Computers/RVPC/open-so...
The recommended dev board, with a USB programmer/debugger interface for your PC, plus 5 of the 20 pin chips, costs $8.35 about the same as a bare 65C02 chip.
https://www.aliexpress.com/item/1005004895791296.html
You can make your own cool shit like this, which uses the $0.10 8 pin chip.
https://www.youtube.com/watch?v=1W7Z0BodhWk
It's as easy to learn the instructions of as a 6502 -- there are fewer of them! -- and far easier to write useful code for.
MUCH easier to learn than a 68000, and no more difficult to use. TBH the A and D register split always annoyed the hell out of me in early Mac days.
musicale
Sounds nice, but the 6502 is certainly real, available hardware that you can buy and set up on a breadboard.
There are tutorials on youtube for it as well, such as Ben Eater's tutorial.
ergonaught
6502 and 680x0 were just a delight. I learned C (and later C++) solely because I couldn’t escape x86 anymore and hated assembly on those chips.
Still do, really, though I’m decades beyond wanting to write anything in assembly now.
ack_complete
I love 68K. So nice to read with the separated data/address registers, and between the instruction set and addressing modes you can easily translate idiomatic C into reasonable 68K assembly.
Main downside is that with 68K you're more likely to be loading your program into an OS rather than bare metal hardware, and have to deal with things like relocation.
bb88
I got into 6502 assembly when trying to do bit manipulations on an Apple IIc back in the day.
The problem was that Applesoft basic set the high bit on data going out a serial or parallel port which was a problem for printing and sending data out through a modem. So if you wanted to keep the high bit one had to use 6502 assembly.
blkhp19
It's also a fun one to write an emulator for. There are plenty of example programs out there to test, and they draw graphics by writing bytes to a frame buffer at some offset in memory. You can read from that region in memory, interpret each byte as a color from a preset palette, and use it to display visual output / graphics.
I wrote one in Swift a few years back, and then ended up developing it further into an NES emulator capable of playing Donkey Kong. It was a great learning experience.
analog31
In addition to be a good starting point for programming, the 8-bit micros are also a good way to begin learning about the hardware side of microprocessor systems, since the external stuff (memory chips, etc.) was correspondingly simpler as well. And without pipelining, you can form a more straightforward mental model of what the system is actually doing.
For me, it was Z80, just because Radio Shack had a book on it. I never actually built or programmed a Z80 system, but I still fall back on that knowledge when working with microcontrollers.
musicale
I think the Z-80 is sadly out of production at this point, but the eZ80 SoC is still available, so hopefully you can still build a hardware CP/M system!
Of course there are also synthesizable FPGA implementations, cycle-accurate software implementations, etc.
dhosek
I’ve only ever learned two assembly languages: 6502 (when I was in elementary school in the early 80s) and 370 (my senior year of high school when I had access to the UIC mainframe thanks to taking night classes there). I can roughly follow the output of godbolt on those rare occasions that I’m curious enough to bother, but the complexity of modern CPUs and computer architectures are such that I don’t know that I really need to deal with assembly language now. That said, my mental model of how a computer works at a low level is very much based on how the Apple II was set up.
WhitneyLand
Same, learned as a kid. What was your motivation?
Mine was wanting to make games and hitting the performance wall in basic.
kiwih
At my institution we teach MIPS, or rather, we teach MIPSY, which is our own version of MIPS which includes a bunch of helper pseudo-instructions.
It's taught to all computer science and software engineering students. Most students would take it in their first year, second semester.
We cover everything from the basics to hand-compiling code with functions, stacks, arrays, pointers etc.
We have our own emulator and even web platform for students to step forward (and backward!) their code: https://cgi.cse.unsw.edu.au/~cs1521/mipsy/
I cannot agree that the simplicity of the 6502 wins over the 68000.
The 68000 has more registers and wider data types: but the registers are all uniformly the same. It's really just two registers A and D, copied a bunch of times in to D0 to D7, and A0 to A7. Whatever you can do with D0 can be done with D3 and so on. Some A's are dedicated, like for a stack pointer.
Simplicity of structure has to be balanced with simplicity of programming.
It's not that easy to program the 6502, because in moderately complex programs, you're constantly running into its limitations.
The best way to learn how to hack around the limitations of a tiny machine is to completely ignore them and become a seasoned software engineer. A seasoned engineer will read the instruction set manual in one setting, and other pertinent documents, and the clever hacks will start brewing in their head.
You don't have to start with tiny systems to get this skill. When you're new, you don't have the maturity for that; get something that's a bit easier to program with more addressing modes and easier handling of larger arrays, more registers, wider integers.