I started on PIC16 assembly, and dabbled in a bunch of other architectures, but my favorite in terms of cleanness has been MIPS32.
Nitpick: you can still buy new made 6502s, MCUs with 6502 cores, and peripheral chips from Western Design Center. They sell through e.g. Mouser:
https://www.mouser.com/c/?m=Western%20Design%20Center%20%28W...
I can't even guess what you might be referring to.
I've coded on a bunch of embedded 8-bit platforms over the decades, and 6502 is great. A, X, Y registers - it's really quite simple. It has various standard and useful addressing modes. It has pretty much the same status register that exist in modern 8-bit MCUs. There's nothing "deeply flawed" about it.
32-bit MCUs are probably a bit too complex for a beginner, 8-bit MCUs will teach a newcomer a lot about the basics of computing in an easy to learn way. It will teach them the significance of "a byte" and working with raw data that maybe you don't exactly get with 32-bit MCUs. There isn't that much to master with a 6502, it's pretty simple, but amazing things can still be done with it.
Where it becomes "deeply flawed" is if you're trying to develop large, complex programs for it, mainly because there's no way to efficiently implement pointers or local variables -- you only have 3 registers, none of which are truly "general purpose", and none of which are wide enough to hold a pointer; and stack operations are severely limited. (This also means that writing a C compiler that targets 6502 and generates efficient code is almost impossible).
So, in idiomatic 6502 code, all variables are global; and if you need dynamically managed objects, you keep track of them using indices into statically-allocated arrays. This is difficult to scale as your programs get large and complex, because at some point you're going to waste an afternoon finding out that your "tmp7" variable in one routine is getting clobbered by another routine 5 levels deep down the call chain that also uses "tmp7" for some unrelated purpose.
It was a perfect processor for its time and its target market, but it made heavy design compromises to achieve its goals, and Moore's law quickly made those compromises obsolete.
Your overall argument is perfect, but I'd question the use of "quickly" since people were selling essentially 6502-based stuff for how long, 20 years at least? From the Apple II in 1977 to the SNES which was released in 1990 and still getting games in 1995, so that's 18 years of that CPU being highly relevant and worth learning.
Of course, you're 100% right that, assuming money was no object and you could buy and use whatever hardware you wanted to, it wasn't long before you could escape those compromises since the x86 and the 68000 (and probably others I don't know) brought much better architectures to those who could afford them.
The early ARM ISAs are good, as you say.
What is particularly funny about your example is that 40 years later you still cant do multiplication or addition in js. You have to install packages (that are multiple computers in size!) after you make up your mind which of the 20+ different modules (read: "dependencies") has the right kind of multiplication for you! I'm not bitter, it's objectively ridiculous :)
* it should actually be c = a × b Without the asterix, we did actually have arithmetic reasonably standardized before IT de-standardized it.
But it's true that with only 8 bits, the problem happens very soon. However, if one doesn't want to solve basic problems "the hard way", one probably won't be interested in assembly programming anyway.
I don't think the 6502 would be a good fit because zero-page doesn't really translate to any useful modern concept. Quite a lot of 6502 coding is Zero-page management.
I went with 8 bit AVR as an instruction set for my silly fantasy console project. It has an in-browser editor and assembler to let people write 8 bit code. The AVR has the best 8-bit instruction set I have found, it's still not perfect (only loading constants to some registers) but definitely built with the hindsight provided by it's predecessors.
If you wanted to avoid the management of data types, I would suggest an instruction set with floating point registers. The same management of bytes into words and dwords, signed and unsigned etc. has to happen on a CPU without floating point support. It's an added complication, which you may or may not want to expose students to.
If the intent is to use Asm to teach from the point of view of "every instruction is a clearly defined action" I would use something with 32-bit ints and 32-bit floats.
If you wanted people to feel our pain, go with 6502, Z80, or PIC depending how sadistic you are.
Granted, this extends across a wide range of assembly languages, but it'd be nice to start with a instruction set without this issue.
[1] https://youtube.com/playlist?list=PLowKtXNTBypFbtuVMUVXNR0z1...
It's totally not the same thing of course. A whole lot of transistors and clock speed go to making that feat possible.
If you want to learn a small, yet powerful instruction set with a few quirks go for ARM v6M. It‘s still in meaningful production (no the Monster 6502 doesn‘t count), has good platform support in the latest open source toolchains (debuggers, compilers, assemblers, linkers, etc.).
If you value openness of the architecture enough to deal with a less mature platform (as of early 2025) then pick a RISC-V MCU instead. If you can‘t decide pick a RP2350 :-).
The ARMv6M instruction set is small and no loading constants doesn‘t require long winded instruction sequences if you do it as documented (PC-relative load instead of shifting in immediate data). You don‘t have to deal with self modifying code and/or the zero page to index memory. Your registers are the same width as the address space. Yes it‘s 32 bits, but that makes it simpler to learn, use and teach than all 8/16 bit and most 16 bit instruction sets I’ve seen because you don‘t have to work around to narrow registers for common operations. To anyone who thinks this sounds boring: don‘t worry ARMv6 still has enough quirks you can use for code golfing.