Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

On a slightly related note, chances are good anyone reading this has an 8051 within a few meters of them - they're close to omnipresent in USB chips, particularly hubs, storage bridges and keyboards / mice. The architecture is equally atrocious as the 6502.

btw: a good indicator is GCC support - AVR, also an 8-bit µC - is perfectly well supported by GCC. 8051 and 6502, you need something like SDCC [http://sdcc.sourceforge.net/]



> The architecture is equally atrocious as the 6502.

I only ever hear glowing/nostalgic reviews of 6502 programming, I guess from the retro/8bit gaming scene, curious what you find so atrocious.


6502 is awesome to program from assembly.

What makes the 6502 atrocious for C is:

- internal CPU registers are 8 bits, no more, no less and you only have 3 of them (5 if you count the stack pointer and processor status register).

- fixed 8-bit stack pointer so things like automatic variables and pass-by-value can't take up a lot of space.

- things like "access memory location Z + contents of register A + this offset" aren't possible without a lot of instructions.

- no hardware divide or multiply.

Many CPUs have instructions that map neatly to C operations, but not 6502. With enough instructions C is hostable by any CPU (e.g. ZPU) but a lot of work is needed to do that on the 6502 and the real question is - will it fit in 16K, 32K, as most 6502 CPUs only have 16 address lines - meaning they only see 64K of addresses at once. Mechanisms exist to extend that but they are platform specific.

IMHO Z80 is better in this regard with it's 16-bit stack pointer and combinable index registers.


> - fixed 8-bit stack pointer so things like automatic variables and pass-by-value can't take up a lot of space.

Also, the stack isn't addressable. The only stack operations the CPU natively supports are push and pop. If you want to access values anywhere else on the stack (say, if you're trying to spill a couple of local variables to the stack), you're going to have a bad time.


I've never programmed on a 6502 before and have only read about it; isn't the stack addressable in the zero page?


No, the stack is in the next page up ($0100 - $01ff). While it's accessible as memory, the 6502 doesn't provide any addressing modes specific to this page; accessing it involves multiple instructions, and requires the use of the X register as a temporary.


Got it; thank you for the clarification! Someday I'll try my hand at some 6502 assembly.


6502 was nice only in comparison with Intel 8080/8085, but it was very limited in comparison with better architectures.

The great quality of 6502 was that it allowed a very cheap implementation, resulting in a very low price.

A very large number of computers used 6502 because it was the cheapest, not because it was better than the alternatives.

For a very large number of programmers, 6502 was the 1st CPU whose assembly language they have learned and possibly the only one, as later they have used only high-level languages, so it is fondly remembered. That does not mean that it was really good.

I also have nostalgic happy memories about my first programs, which I have entered on punched cards. That does not mean that using punched cards is preferable to modern computers.

Programming a 6502 was tedious, because you had only 8-bit operations (even Intel 8080 had 16-bit additions, which simplified a lot multiply routines and many other computations) and you had only a small number of 8-bit registers with dedicated functions.

So most or all variables of normal sizes had to be stored in memory and almost everything that would require a single instruction in modern microcontrollers, e.g. ARM, required a long sequence of instructions on 6502. (e.g. a single 32-bit integer addition would have required a dozen instructions in the best case, for statically allocated variables, but up to 20 instructions or even more when run-time address computations were also required, for dynamically-allocated variables.)

A good macroassemmbler could simplify a lot the programming on a 6502, by writing all programs with a set of macroinstructions designed to simulate a more powerful CPU.

I do not know whether good macro-assemblers existed for 6502, as in those days I have used mostly CP/M computers, which had a good macro-assembler from Microsoft, or the much more powerful Motorola 6809. I have programmed 6502 only a couple of times, at some friends who had Commodore computers, and it was weak in comparison with more recent CPUs, e.g. Zilog Z80 (which appeared one year later than 6502).


> I do not know whether good macro-assemblers existed for 6502

They certainly did. I don't know about the communities that grew around Commodore, Atari, or other 6502-based computers, but in the Apple II world, there were multiple macro assemblers available. Possibly the most famous was Merlin. As a pre-teen, I used the Mindcraft Assembler. Mindcraft even sold another product called Macrosoft, which was a macro library for their assembler that tried to combine the speed of assembly language with a BASIC-like syntax. The major downside, compared to both hand-coded assembly and Applesoft BASIC (which was stored in a pre-tokenized binary format), was the size of the executable.

Edit: Speaking of simulating a more powerful CPU, Steve Wozniak implemented the SWEET16 [1] bytecode interpreter as part of his original Apple II ROM. Apple Pascal used p-code. And a more recent bytecode interpreter for the Apple II is PLASMA [2].

[1]: https://en.wikipedia.org/wiki/SWEET16

[2]: https://github.com/dschmenk/plasma


Wozniak’s sweet 16 was along these lines:

https://en.m.wikipedia.org/wiki/SWEET16


6502 is nice to program in assembler. For a compiler it is an atrocious platform to support. The limited stack, the 8 bit limit, the zero page idiosyncrasies, the page crossing bugs (some corrected in 65C02), etc. Z80, while also full of adhoc-isms is a much more pleasant target for a C compiler, only just for its 16 bit register and stack.


> curious what you find so atrocious.

In the context of the original post, it's a bad target for C — I have no clue about other 6502 use :)


One thing to keep in mind while programming AVR in C is that it still is small-ish MCU with different address spaces. This means that if you do not use correct compiler-specific type annotations for read-only data these will get copied into RAM on startup (both avr-libc and arduino contain some macrology that catches the obvious cases like some string constants, but you still need to keep this in mind).


Newer parts actually do have flash mapped into memory address space accessible through normal LD instruction, though I'm not sure if avr-libc moves constants into it automatically or still needs that PROGMEM/__flash annotation.


For 6502 fans, there's a new port of Clang and LLVM that seems to be doing some nice code generation. See https://llvm-mos.org/


Hope RISC-V will displace 8051 over time. It's such an absurd thing to extend this architecture in myriad non-interoperable (although backwards-compatible with OG 8051) ways. And don't forget about the XRAM nonsense. Yuck.


AVR was designed much later with a C compiler in mind. 8051 while atrocious is much cheaper to license and fab than an ARM Cortex-M. These applications will probably go RISC-V in near future.

On the real low end PADAUK is king, at under 3 cent retail. They don't even bother with a C compiler and instead have a macro assembler on steroids called Mini-C (there is also sdcc but I never used that having needed every last 13 but word of ROM). Programming these, with 64 bytes of RAM, is strangely refreshing - no fancy abstractions, microsecond-precise instruction timings.


the 6502 has a single 16-bit address space with some parts (zero page, stack) addressable by means other than full 16-bit addresses. the 8051 has 16-bit read-only code space, 16-bit read/write external memory space, and 8-bit internal memory space, except half of it is special: if you use indirect access (address in an 8-bit register), you get memory. but if you encode that same address literally in an instruction, you get a peripheral register.

at least that's the part I remember




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: