Hacker News new | past | comments | ask | show | jobs | submit login

I think one great way to do this is to get a Commodore 64 emulator (or Atari 2600 etc) and start writing and learning 6502 assy. Arguably its one of the last instruction sets that was designed with humans writing code in assembly (and not in some higher level language) making it excellent learning language. You can readily run your code in emulators and for not too much $$$ you can pick a real hardware from EBay to really run it on HW.

And once You think you’ve run hw to its limits there are plentiful demos and examples around to blow your mind watching what people have been able to do with these machines (often in obscure ways).






Commodore 64, sure, but I wouldn't recommend the Atari 2600 for beginners! I wrote a small game for the 2600 years ago, and it's a tricky little machine. It doesn't even have a video frame buffer, so you have to do things on the fly, depending on which line of the screen is being beamed (think of old-school CRTs).

Indeed, a whole book was written about it: https://en.wikipedia.org/wiki/Racing_the_Beam

The 2600 is fascinating and fun to code for, but for asm newbies I'd recommend the C64 or NES...


Or perhaps the GBA, which is modern enough to have a framebuffer, but old enough that the framebuffer is just sitting there at a known address.

I can additionally recommend the GBA as an interesting fixed target. Lots of folks recommend an Arduino for this, and those are great little machines, but they have two problems. 1. they can be a bit too limited for a lot of potential projects, and 2. because they are hardware projects boards, they don't do very much on their own. Figuring out what to hook them up to is half of the fun, but it can be a daunting choice for a beginner, especially someone learning assembly language for the first time.

The Gameboy Advance is a marvelous little platform. It runs a modified ARM7, so if you learn its machine language a lot of that knowledge will transfer into the industry. It runs at a brisk 16 MHz, which is fast enough that it can run compiled C code quite comfortably, but slow enough that performance still matters very much once you try to push the system's limits. Even if you run it in C rather than assembly (perhaps ideal for a true beginner), the whole machine is chok full of bare-metal standbys. Most of the graphics and sound hardware is memory mapped, requiring very specific bit patterns written to special addresses to tell the rest of the hardware what to do. Working with graphics requires an understanding of interrupts and synchronization. Finally, being a games system with a screen, buttons, and a speaker built in, there's a lot of projects you could build... but the easiest is to make a game! And what a blast that system is to make games for. Powerful enough to do all sorts of compelling things, but simple enough to program (even as a beginner) that you can easily have backgrounds and sprites onscreen in about a day of effort.


GBA = Game Boy Advanced

I learned assembly on a TRS-80 Color Computer (6809 CPU.) Interactions with the machine were fairly straightforward.

The 6809 was a joy to program in assembly language. I enjoyed some aspects of Z80, and loved the puzzle of getting things done with 1802 and 6502, but 6809 was, for me, the sweet spot.

Two stack pointers, one for call/return, the other for push pop data.

I've always been skeptical of using retro machines to learn low-level programming.

While the processors are simple, making non-trivial programs is hard, because the machines as a whole have lot of limitations, making programming very intricate, compared to more modern systems (say, 16-bit 80x86, but I guess even Amiga and so on).

If the target it challenge for the sake of challenge, then nothing makes those machines special, I mean, one can code directly in machine code if that's the intention :-)


I had to teach an class recently that required introducing students to assembler. I designed an extremely RISC architecture (we’re talking mov into pc for control flow, r31 is “suggested” for use as a stack pointer) but gave it just enough that they could write more advanced instructions in assembler macros, which they designed themselves. I think it worked out well!

One homework problem I had in a computer architecture class circa the late 90s was, here's a hypothetical computer, now implement this instruction using the given microcode definition. I really enjoyed it because I was able to do it in much fewer micro-ops than the instructor expected.

In the early 80's my Computer Organization class the entire semester was dedicated to building a simulated 4 bit computer, with I/O channels (disk, screen, keyboard, printer) and a stripped down basic interpreter, and stripped down language compiler (it was a made up language).

We had to simulate everything, and the final project was to take the professor's Basic program and execute it correctly, and compile his other program and then execute that correctly.

That class was the absolute best thing I ever did, I learned so much in that class. It was the only class that I went to every day and took seriously, I got the only A in the class.

I had started programing back in the mid-70's by the time I got to college in 82 I had a bunch of side jobs writing code. I didn't focus too much on my college career, I was working my side programming gigs, and I was tutoring other students. That class got my attention and I loved it.


Finally an application for MIX!

Well, kinda. The architecture is minimal but I had a strong focus on orthogonality, a linear address space, and clean instruction decoding; so much so that I named it REGULAR ;) The ISA (https://github.com/regular-vm/specification) was specifically selected so that traditional control flow could be created with the use of only one temporary register (some take a bit of work; conditional branches decompose to branch islands for example).

Yeah I was being tongue in cheek. Your approach sounds great for encouraging people to think about and find solutions to specific issues.

MIX was, in theory, supposed really to be the opposite: so universal/generic that you'd ignore the language and focus on the lesson. Similar to the motivation for using Scheme in SICP. Obviously times have changed :-).

Sort of the difference between putting on eyeglasses to see the world better (MIX) or putting on eyeglasses to learn about how lenses work.


Have you seen MMIX? It's my favorite RISC architecture (unlike MIX, which isn't RISC)!

If you end up doing anything embedded you’ll likely be working with machines that also have very limited capabilities (you may be debugging by toggling a few pins and looking at the results on an oscilloscope) so I’d argue that these old machines can provide a lot of infrastructure to get comfortable with thinking this way.

I think the opposite is true because those machines were built around assembly programming. The hardware was essentially the software development framework.

Check out this assembly programming series, it's less assembly code on the Amiga to get something on screen or getting mouse/keyboard input than with highlevel languages and APIs/frameworks today:

https://www.youtube.com/watch?v=p83QUZ1-P10&list=PLc3ltHgmii...


A couple of decades ago there was a demo tutorial called "Asphyxia demo trainer"; it explained many effects and even basic 3D, both in assembler and, in a revised version, in C.

> I think the opposite is true because those machines were built around assembly programming.

This isn't true. It was extremely simple to get something work based on that tutorial, and to move to something more complex.

Doing that on an 80s 65xx-based machine would have been significantly more difficult, because that generations had significant limits in the coprocessors (AFAIK, the C64 could play music in games, but it was a workaround; it wasn't designed to do so).

Surely Amiga is easier, as the coprocessors were significantly more capable, but the parent based the discussion on C64 development.


> I've always been skeptical of using retro machines to learn low-level programming.

> While the processors are simple, making non-trivial programs is hard, because the machines as a whole have lot of limitations, making programming very intricate, compared to more modern systems (say, 16-bit 80x86, but I guess even Amiga and so on).

Programming in those time was an art. Now some people have 32 GB of RAM and they are not able to use it efficiently.

> If the target it challenge for the sake of challenge, then nothing makes those machines special, I mean, one can code directly in machine code if that's the intention :-)

I've seen OS's that at 20 MHz and 4MB RAM did things that Windows, Linux or MacOSX cannot do today with 1000 times more resources. It is really a shame.


In the late 90s, I worked with a small team, about four of us, and ported a DSL soft modem from Windows NT running on a Pentium II running at 450Mhz to VxWorks running on an ARM SA110 running at 120 Mhz. The original software and hardware team that developed the Windows drivers claimed that it would be impossible to meet the processing requirements on that platform. In the end, under worst case line conditions (R-S correction thrashing like mad) we could still get it to run with the clock turned down to 60Mhz.

Because that was all the processor was doing. No virtual memory, no disk, no IO, no graphics. Just feeding the DSP data on one side and NAT routing on the other.

Under the same line conditions, the PII running windows was useless running at 450Mhz. Mouse would barely respond, keyboard was lagging, screen wouldn't update.

Like you said, depending on what you are trying to achieve, you can perform near miracles on confined hardware if you have confined demands.


Which is why game developers love consoles so much.

Smaller world, smaller expectations. I know people who started with Amigas and they went straight to C, no assembly. I started on 6502, skipped 16bit and went to ARM2. Doubt I would have learned assembly if not for the 6502, and the need to use it. The simpler the machine, the better. Sure it might be faster to get some quick wins if the computer has a blitter, but if the goal is to learn low level programming, then writing the blitter yourself is probably the way to start. The more extra bits there are on the system, the harder and less interesting it is to program for at a low level. Modern OSs are abstracted for a reason.

Smaller expectations, smaller programs, so you don't learn how to structure larger programs.

It's the same as learning on GW-BASIC or equivalent: You learn some bad habits due to the environment which you must unlearn the moment you move on to a real system.


Yes. That is how people learn. Or is teaching children arithmetic pointless because they won't learn how to simplify algebraic expressions? Learn the basics, then add more complexity.

The 6502 was a real system. Conversely, I'd say Visual Basic is a terrible environment and I have a few friends that made millions using it, so, not sure who gets to be the judge.


> And once You think you’ve run hw to its limits there are plentiful demos and examples around to blow your mind watching what people have been able to do with these machines (often in obscure ways).

What blew my mind was using a modern C++ compiler to build optimized software for that old hardware. Here's an example with the Commodore 64 [0].

[0]: https://www.youtube.com/watch?v=zBkNBP00wJE


Anyone using Turbo C++ on MS-DOS already had that experience. :)

Hence why microcontrollers like ESP32 are much more poweful than many think of.


Shameless plug: https://github.com/akkartik/mu#readme uses an instruction set designed in the 80s: x86.

I learned mips in a college class and quite enjoyed it. How does mips compare to C64 asm? I don't know any other asm besides mips (unless zachtronics games count) and but have been playing around with the idea of writing a simple asm OS. Would C64 asm be a good choice? I've also heard that m68k asm is nice. How do the three compare?

6502 has three 8 bit registers, A, X and Y. X and Y are used for indirect addressing and the like. MIPS has 32 32bit registers, or 64bit and maybe floats and doubles, and you can use any of them for anything. 68k is more like a bigger 6502 than a MIPS. Personally I prefer programming a RISC chip (like the MIPS or an ARM), but the choice to make is more around the complexity of the other hardware, than the CPU itself. For assembly, the Nintendo 64 was the sweet spot, IMHO, as it was the last one where we ran as the kernel and could do anything.

I haven't done any MIPS assembly. But 6502 assembly is very simple. The only tricky bit is the instruction set is very non orthogonal. m68k though is very cleanly octagonal.

MIPS is highly orthogonal.

I think it is more up to date to grab a Arduino, ESP32, Raspberry Pi, Hydra based console, and program it like the old days.



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

Search: