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

I can't imagine being a programmer without starting out by becoming proficient in assembler. It takes a lot of mystery out of programming languages because you know whatever the syntax is it all ends up as branches, calls, stacks, registers and memory accesses.


I would heavily recommend first learning assembly with an ISA that's not x86, though. The x86 ISA has just as much cruft as C, e.g. all the overlapped increasingly-sized registers, the now-irrelevant segment registers, etc. And x86 has some stuff that's not legacy, but which makes learning much harder — e.g. assembler-level instructions like LEA that compile to a set of entirely-different opcodes of different shapes depending on what you do with them. (IMHO, for best learning, you should be able to easily disassemble object code in the ISA "by hand" back into assembly, with just an opcode chart for reference. Doing this with arbitrary x86 assembly would be quite the challenge.)

I'm not sure what to recommend as an optimal learning ISA, though. Ideally something that's mostly RISC, with a small but unified memory model, and no virtual memory, and which has all the math ops that embedded RISC ISAs never bother to implement. (In the end, probably no real architecture ever made that exact set of compromises, and so it'd have to be something made up — some kind of bytecode abstract machine ISA designed specifically to be used in education, an ISA equivalent to languages like Logo or Scratch, or OSes like Minix.)

In practice, I think I would recommend learning assembler by programming for the original Gameboy's LR35902 ISA (which is almost, but not exactly, the Z80/8080 ISA). Not because it's the optimal learning ISA per se, but because it gives you a complete machine including graphical video output, with a compact unified address space (no separate IO-register read/write ops), modern tools that target it, and good emulators that almost always include built-in debuggers and memory viewers — where, as well, the memory is small enough to get it all on-screen and have room left over.

Oh, and unlike other ISAs, where people either never hand-write code for them, or where no hand-written code survives in a readable form, with LR35902 we have several complete projects with hand-written assembly codebases (or, well, reverse-engineered + annotated disassemblies of originally hand-written assembly — just as good!) around to be studied. And, of course, they're just the sorts of things kids interested in computers would be interested in studying the workings of: video games! (https://github.com/pret/pokered is a shining example here.)


I feel very lucky I learned on the 68000 in the original Mac. If a CPU could ever be considered a work of art, it was the 68000


If you want to do embedded I would kind of agree(But C is low level enough), otherwise... I'm not so sure.

Low level languages teach a lot of habits I don't like, and they don't teach as much about working in a modern high level environment on complex software.

Everyone should probably be vaguely competent with C, but I wouldn't call it a top priority.

If you're thinking about the underlying machine stuff when coding in Python, you're kind of just accepting leaky abstractions. If you're in the habit of first principles thinking, leaks seem normal.

C doesn't really seem to layer all that well. Whenever I code in C, I usually have to dig down to the SDK API level, and I wind up reading 10 other files to make a change in 1.

High level languages make it clear when something isn't DRY, or an abstraction leaks, or something isn't usable without modification. It's unusual, you notice right away, and you want to fix it because it obviously doesn't fit.

Low level languages make everything feel totally patched together. Encapsulation just isn't a big thing in most of it. It's almost like looking at an old point to point wired TV set compared to a rack of servers.

You might be able to write some amazing ASM code that feels as modern as some top notch Kotlin... but I'd call that an expert, not just a competent person.

And worst of all, the compiler can't catch many bugs. It's not like Rust. Or even Python. Low level languages don't teach the art of making sure that the computer has your back, the way Rust might. They normalize just entirely relying on your own skill, to the point where some C devs don't even seem to want the compiler to eliminate large classes of bugs for them.

High level languages teach a real appreciation of abstraction and safety, and standardization, that I don't feel like I really learned with C.


I agree with everything you said here. I'm not saying we should stick to bare metal programming even if we aren't doing embedded. There may be a problem that could be solved easily with inline assembly or there may be a bug that can't be understood if the programmer doesn't understand what is going on at the CPU level. Assembler is a tool in my kit, but not everybody needs to use it. I like to understand my computer from top to bottom, but sticking to higher level abstractions is where I spend most of my time.




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

Search: