# Should assembly language be taught in an introductory course (or soon after)?

Should ye ole' fashioned assembly language be taught to help students develop a sense of how actual underlying computational hardware supports/allows running their higher-level or more abstract software?

Something with (a limited amount of) a linear address space (global state memory) and a program counter with jumps (conditional control flow or GOTOs).

Using something like Knuth's MIX, or the CARDIAC cardboard computer (this was actually used to teach programming in an introductory computing for non-programmers course I audited at Berkeley in the late '70's), or perhaps an emulator for an 8-bit retro-computer (such as Apple II or Altair) that can run inside a web browser.

I think there is very limited benefit in teaching assembly so early, and it's more likely to just scare away your students.

When I started learning programming, I thought bare-metal OS development was really interesting, and I started to learn about it (mainly through OSDev). But frankly, assembly was far beyond my level at that point, and it was hard to get anywhere beyond the tutorials they give. Consider that:

• Beginners often have problems with learning the syntax of the language, and the underlying conceptual problems ("how do I design this?"). Your students may not be ready for that after an introductory class—learning the concepts and thought processes (how to think like a programmer) is far more important than any language, and assembly only clouds that by making you think about memory, registers, jumps, etc.

• Your students probably won't ever need assembly, and they almost certainly won't be writing much unless they go into fields like embedded development, OS development, etc. Even then, it's more likely that C (or a similar low-level language) will be used.

• Assembly is intimidating. It's not something that it easy to read, understand, and write. Aside from the technical problems of teaching and learning, it's just scary, and when I tried to learn assembly, it just led to frustration and not a lot of progress.

My opinion is that you should develop the higher-level concepts first, and make sure your students have a solid understanding of how to write code logically. Then, you can begin to 'remove the stabilisers', introduce memory management, and then finally lead to assembly, if that's what you want to teach.

• Is it possible that the "scare" intimidation factor is a modern myth? Or perhaps a result using too high a level language for too long? The CARDIAC computer fit on one sheet of cardboard, and a class of (IIRC) mostly non-STEM undergrads seemed to have no problems with programming it for an assignment. And plenty (perhaps tens to hundreds of thousands?) of 14-17 year old kids learned to poke 6502 asm instructions. – hotpaw2 May 23 '17 at 15:55
• @hotpaw2 I think it'll be hard to find an answer to that, but it's an interesting idea. I'd conjecture it's more a case of "I only learned 6502 assembly, so it was easy for me" being said by those who did thrive, and anyone who was unable to make the jump simply dropped out and gave up completely. I'll have a look round to see if I can find any research about how students learn in assembly, compared to a higher language, though. – Aurora0001 May 23 '17 at 16:01
• “they almost certainly won't be writing much unless they go into fields like embedded development, OS development, etc.” — or even if they do. I am an embedded OS developer and I write maybe a handful of lines of assembly a year. In a busy year. – Gilles 'SO- stop being evil' May 23 '17 at 21:33
• The point would likely not be to train students how to write applications in assembly language, but more so that they learn enough about (near 1-to-1) machine code, to better understand how a CPU/processor actually carries out the real work. – hotpaw2 May 24 '17 at 22:37
• @hotpaw2 Ah, right, sorry about that; it appears I've missed the point a little bit. I think the answer would depend on what language you plan to teach—a Python class probably wouldn't need an awareness of assembly just yet, but a C/C++ class might find it helpful. I'll revise my answer a little if you edit with that info in the question. – Aurora0001 May 25 '17 at 14:55

While there is a natural appeal to teaching assembly programming (hey, we can build everything up from first principals!), early students really need to master sequencing and organization at a higher level first. There is a surprising amount of abstract thought going on in looping and determining ending conditions even without limiting your branching cases to ZERO and NEGATIVE, or having to worry about whether your mod operation just overwrote the B register.

I would avoid doing it as your first activity. That said, if you do want to go early into assembly programming, Human Resource Machine is an extraordinary resource, and we purchased a site license for use at our school. We currently use it before bringing the kids into 6502 Assembly. They get instantly addicted, and it makes many of esoteric the concepts rather visual.

• TIS-100 is another great resource in this area. – Adrir Jun 6 '17 at 20:43

Yes: Some machine level behaviour is important at an early stage, to retain a diverse interest in the subject.

Some students will find it necessary to understand what a computer is doing 'under the hood', but others will have massive problems understanding how high level constructs can be broken down into simple load/add/store sequences.

Web simulators like Peter Higginson's RISC simulator definately need to be presented, and I've had good success in modelling a Fetch/Decode/Execute pipeline as a group activity, where assembly language is a key part of enabling the activity.

However, I think it is the simple load/store (or RISC) architecture which is the key thing to describe, rather than the details of the assembly language. Using a simple instruction set is just a natural part of explaining this type of architecture.

If you focus just on the higher level languages, you'll probably not notice, but the students who have a more practical view of physics/electricity (or just how machines work) will forever be wondering what happens before their code gets to main(). These are the students who will go on to be embedded developers/ASIC designers or CPU architects (or rocket engineers).

• ... or they'll become compiler developers / performance tuning experts. I got into computer programming after messing around with electronics / digital logic as a hobby in high school, and I've always loved knowing how things really work. And now I code-golf in x86 machine code for fun :P – Peter Cordes Feb 23 '18 at 6:01

I don't think there's much point teaching students to write assembly code purely for the sake of it. There are more useful and productive tools / languages / concepts that would be a better use of time. However, I'm a big fan of giving students some exposure to assembly code in order to teach some key concepts rather than skills:

Keen students often want to know the answer to the following questions:

1) How does a computer actually work?

2) What makes one computer faster than another?

It's hard to answer those questions fully without having a clear grasp of the fetch / decode / execute cycle. If students understand how computers store and process instructions there are huge consequences on the programs they can go on to create in terms of efficiency, reliability, performance and robustness.

If the 'introductory course' is an intro to programming generally, I'd probably avoid assembler. If it's an introduction to Computer Science which includes more than just writing code, I'd say some exposure to assembler is pretty essential.

I use tanks.withcode.uk as a Little Man Computer CPU simulator that controls little tanks that students have to program around an obstacle course. At the end of that module I don't really mind if students can't remember how to write LMC code but I do expect them to be able to explain the fetch / execute cycle. The brighter students will also be able to explain the performance and security implications of the Von Neumann processor architecture.

This video explains how LMC assembly can help explain some key CS concepts.

If nothing else, briefly exposing students to assembler programming makes them appreciate how much easier writing code is in a high-level language.

• Welcome to CSeducators Stack Exchange! This is a very good answer, and quite to the point. Well done – ItamarG3 Jun 14 '17 at 6:36

Which Assembly?

Little Man Computer is so consistent and simple it's part of the syllabus for teenagers in UK. There are good (free) web simulators for it, and a large amount of resources.

ARM assembly is highly consistent, clear, and logical. Any student with a decent grasp of logic should have no problem with it. But I wouldn't teach it as an intro to programming unless your programming course was tightly coupled with sessions on logic and debugging, and your students were mostly selected as being strong in / enthusiastic about pure maths.

A lot of programming isn't about logical reasoning (although specific areas e.g. debugging, are almost 100% logical reasoning), and teaching logic-heavy languages is a great way to select for the subset of students that love logic.

If that's your goal, and you're happy with driving away students who would have been strong programmers given time to learn logical reasoning, it's good. If your student intake is - for instance - a subset of a Math class, it's probably not an issue, and they may engage strongly with it.

• Perhaps something even simpler. The CARDIAC was a 10 instruction, decimal, single accumulator computer that could be described (and run!) on one sheet of cardboard. Knuth's MMIX is another, more RISC like, possibility. Both designed for pedagogy, rather than implementation efficiency vs. gate count. – hotpaw2 May 23 '17 at 16:05
• As I understand it, LMC was specifically designed for pedagogy too. I listed it first because - as far as I know - it's the most recent, most widely supported, easiest to find documentation for (partly because it's still on syllabuses today) – user31 May 23 '17 at 16:18
• I'm not a big fan of LMC. It's too crippled, so basic asm concepts like checking for even numbers by checking the low bit is a major challenge, because the architecture doesn't include an AND instruction or any other bitwise operation. It only has add/sub, load/store, and branch on zero / branch on positive. (And IN / OUT). So you can teach instructions / load / store, but you can't teach manipulating binary. – Peter Cordes Feb 23 '18 at 5:20
• There are less-crippled teaching architectures like LC-3 en.wikipedia.org/wiki/LC-3#Instruction_set, which is a register machine rather than an accumulator machine, and has bitwise AND and NOT. We see some SO questions from people with assignments to write things that are only hard because they need to work around the limitations of LMC or LC-3. Maybe's that's useful as lateral thinking, but some instructors have gone too far out into the weeds. If you're teaching asm with a stripped-down architecture, IMO don't usually make students synthesize left-shift from add same,same, etc. – Peter Cordes Feb 23 '18 at 5:26
• – Peter Cordes Feb 23 '18 at 5:32

Teaching how to write assembly is questionable at best.

Teaching how to read assembly is IMHO crucial, and comes naturally as a part of C/C++ curriculum. For example, try to explain what atomics are, and how they are not black magic, without referring to concepts from the assembly realm.

• It helps that C is essentially structured PDP-11 Assembly language :D – pojo-guy Jul 11 '17 at 1:58

We need to separate the ideal of teaching a student how to be a fully competent assembly programmer, from the utility of using machine-level things like stacks and registers to help them build a model in their mind of what is going on.

For any given model of program execution, like flow charts or state diagrams, some students will take to it easily others will struggle. So I see the main issue is picking the model of execution that helps the student understand it.

Some things like pointers and arrays map directly to a mechanical view of the program and its data. Function calls can be thought of as nested sheets of variables and some students are fine with that. Others find it too abstract and the mechanical view of function calls where addresses are pushed into a what is in effect an array called the stack is easier to understand (for some) even though it has far more working parts.

To me this is an example of deeper issue, in teaching we must use our judgement in choosing a high level description of some part of a programming which has fewer parts, each of which is harder to grasp, or to explain a mechanism of a larger number of smaller pars, each of which is easier to understand.

• Understanding that C compiles to asm is useful in debugging C programs with undefined behaviour. e.g. if your program does something that shouldn't be possible, or crashes in a really weird way, then you probably did something wrong with a pointer to a local variable and stepped on something in the call stack. IDK how far this gets you if you don't actually know asm (just that it exists), and don't have the expertise to backtrack from the symptoms to what might have been overwritten, though. – Peter Cordes Feb 23 '18 at 6:13

I haven't seen this in the thread yet so I thought I'd add it.

I haven't been in any environment where I've felt that starting low level makes sense but I've met others that do. YEARS ago Noam Nisan and Shimon Schocken wrote The Elements of Computing System which builds things from the ground up and I recently learned about this course using the book. I haven't vetted the course but it might be a useful resource.

CS50 AP -- the adaptation I teach for AP CS Principles -- has a lesson on the compilation process in C. The full scope of the lesson can be found here.

While the lesson provides a broad overview of the process, it does expose students to the steps needed to go from source code to assembly code to machine code. As a result it makes understanding assembly relevant. It could very easily be used as a stand-alone lesson.

The programming challenge for this lesson -- Reverse Engineer -- focuses on the very basics of understanding assembly and tasks students with translating assembly instructions into a small C program. It's certainly not a full unit, but something of this scope does give a good introduction to assembly and allows it to be a reference point as the class progresses.

At the intro level this is probably the right amount of assembly to use: just enough to make them aware of it (and to motivate further study) but not too much that it creates more confusion than understanding.

To me, it depends on whether you are really teaching computer "science" or coding/programming.

If this is a genuine "science" course for math and hard science majors, I would teach assembly language early. It underpins the logic structures of most computer languages and many important commands, so if your students are interested in data structures and management, and the "logic" of computation (down to things like electric circuits and networks), assembly language is the way to go.

That said, it is not suitable for most students. Here, you are talking about "cross over" users who are more interested in coding which they will use to create programs than the underlying science. Put another way, these students want to learn "what" rather than "why."

In short, if I were structuring a college department, I would offer an assembly language option but not be surprised if only a few students took advantage of it.

To very loosely paraphrase a famous man, "it depends on what the definition of 'teach' is." A few other answers have sort of approached this point, but none have quite said it.

There is a difference between introducing the fact that assembly language exists and explaining the purpose it serves, and going all out and instructing students in the meaning of each assembly instruction and having them write complete programs in assembly language.

Yes, assembly language is scary, but that alone isn't a good reason to shy away from teaching it. Many people who haven't been exposed to computer science think the entire field is intimidating.

For decades now, novices have basically had the options of learning to code in either high-level programming languages or REALLY-high-level programming languages*. Naturally, that leads to some disconnect about what's actually going on between the code and the processor. It's important for programmers to know that that space is filled by an ordered, understandable process, not magic. But anything more than that (and, arguably, even that much) can wait until after the introductory level.

Assembly is, quite frankly, too low-level for the kinds of thinking that introductory courses are intended to develop. The idea is to get students thinking about loops and lists and stacks and trees; algorithms and data structures. Talking about moving values from register to register hides the forest for the, um, other kind of trees.

Once students get past the first few courses and decide they want to stick with the program, then throw assembly into the mix along with other "necessary but more advanced" topics, like P/NP, I say.

* Compare to "once upon a time," when the default newbie programming language was C, which was a lot closer to assembly, and my answer might have been different.

• Regarding the little apology I just ripped out of your answer, no need to apologize. We're glad you found us :) – Ben I. Jun 21 '17 at 21:15
• @BenI. Cheers. I usually figure the kind of people who care about the apology will be angry about not getting one but the kind of people who don't care won't mind seeing one (or quietly editing it out). – Piyush Parikh Jun 21 '17 at 21:37