← Back to context

Comment by MobiusHorizons

1 year ago

Because these are the primatives that are in use when programming in any language, and there is a benefit to learning the primatives before learning higher level abstractions. For instance we teach arithmetic before calculus.

I see lots of people become pretty helpless when their framework isn’t working as expected or abstraction becomes leaky. Most people don’t really need to know assembly in order to get past this, but the general intuition of “there is something underneath the subtraction that I could understand” is very useful.

The primitives of control flow in programming languages are sequencing, if, while, for, switch, return, and "early return" (goto restricted to exit a containing block). We might compile these into a form that represents everything using conditional jumps, unconditional jumps, and jump tables, but that's not how people think about it, definitely not at the level of programming languages (and even in the compiler IR phase, we're often mentally retranslating the conditional jump/unconditional jump model back into the high-level control flows).

And I could go on with other topics. High-level languages, even something like C, are just a completely different model of looking at the world from machine language, and truly understanding how machines work is actually quite an alien model. There's a reason that people try to pretend that C is portable assembler rather than actually trying to work with a true portable assembler language.

The relationship you're looking for is not arithmetic to calculus, but set theory to arithmetic. Yes, you can build the axioms of arithmetic on top of set theory as a purer basis. But people don't think about arithmetic in terms of set theory, and we certainly don't try to teach set theory before arithmetic.

> For instance we teach arithmetic before calculus.

I don’t think that’s a fitting analogy.

Nearly everyone on the planet uses (basic) arithmetic. Very few use calculus.

By contrast, very few (programmers) use ASM, but nearly all of them use higher level languages.

  • I'd say every programmer uses the constructs in assembly. Just because we have layers and layers of abstraction on top of that doesn't mean it's not valuable to understand the far simpler world that it all sits upon (Granted I understand it sits upon machine code, not assembly, but assembly is probably the closest to machine code that is more human interpret-able without significant effort).

    My first language was BASIC on a V-tech. It's not quite the same but it still was such a fantastic starting point.

    I've tried luring people into programming with Python for example and see them get frustrated by the amount of abstractions and indirection going on. I am really starting to like this idea of starting with assembly.

    • Yeah, my point wasn't that learning ASM isn't valuable, or that we don't use the constructs in higher level languages.

      My point is that the analogy with arithmetic vs. calculus doesn't hold.

      Nearly everyone uses basic arithmetic in everyday life, and a tiny fraction of those use calculus.

      No programmer needs to learn ASM to be able to know how to use higher level languages. And a tiny fraction of them are using actual ASM in their everyday jobs.

      Also, I think you can still learn the basic constructs of how languages work at a lower level without every learning actual ASM. There's no way you can learn calculus without an understanding of arithmetic.

      1 reply →

    • By this token, everyone who counts apples in a market is using the axioms of Peano arithmetic every day.

      The fact that our high level languages compile down to assembly doesn't mean we use assembly in any meaningful sense. My C code will be correct or not based on whether it conforms to the semantics of the C abstract machine, regardless of whether those semantics match the semantics of the assembly language that it happens to compile down to. Even worse, code that is perfectly valid in assembler may be invalid C, even if the C code compiles down to that same assembler code. The most clear example is adding 1 to an int variable that happens to have the value MAX_INT. This code will often compile down to "add, ax, 1" and set the variable to MIN_INT, but it is nevertheless invalid C code and the compiler will assume this value is impossible to happen.

      This relationship between a programming language and assembler is even more tenuous for languages designed to run on heavy runtimes, like Java or JavaScript.

I think comparing assembly with arithmetic is dead wrong. Arithmetic is something that you use constantly in virtually any mathematical activity you will ever do, at least at the under-graduate level. There is literally 0 calculus, statistics, or algebra you could understand if you didn't know arithmetic.

In contrast, you can have a very successful, very advanced career in computer science or in programming without once in your life touching a line of assembler code. It's not very likely, and you'll be all the poorer for it, but it's certainly possible.

Assembly language is much more like learning the foundations of mathematics, like Hilbert's program (except, of course, historically that came a few millenia after).