A few days ago, I ran into an online post where someone pointed out the book “Learn to Program with Assembly” and asked if anyone had ever learned assembly language as a first programming language. I had to smile because, if you are a certain age, your first language may well have been assembly, even if it was assembly for machines that never existed.
Of course, that was a long time ago. It is more likely, these days, if you are over 40, you might have learned BASIC first. Go younger, and you start skewing towards Java, Javascript, or even C. It got me thinking, though: should people learn assembly, and if so, when?
I’m no stranger to assembly languages, but I’m not sure I know a modern and defensible answer to this question. You can find plenty of tutorials, of course (including some from me). There are plenty of cases where a few lines of embedded assembly can make a big difference in a program. Debugging a bad compiler can also require assembly chops. So it seems that at least some people still need to learn assembly. That leaves the question of when to learn it and, as a corollary, who needs to learn it.
My traditional answer would be that everyone should learn it as soon as possible. But that could be because that’s how I did it years ago. I’m not convinced that’s the right answer for everyone today. However, I’ll make my case.
The Case for Early
If you are satisfied writing code to validate zipcodes in Javascript, you probably don’t need to learn assembly. But if you want to really be a top programmer, you are going to have to confront it sooner or later. Learning it early has some benefits. If you understand what’s really going on at the CPU level, a pointer in C doesn’t seem like a tough concept. Being able to look at the output from a compiler and understand what it means is often illuminating when you are trying to learn something new.
However…
The only problem is that modern assembly language is difficult. CPU instruction sets are strange, and there are issues with CPUs that do out-of-order execution. Then there is relocatable code and other details that are easy to trip on and not very useful to know much about.
So there are two ways to go. First, pick an older CPU. Something like the Z80, the 1802, or the 6502 isn’t that hard to learn, and there are a ton of resources available. Don’t have any hardware like that? Who cares? Use an emulator. You can probably even find some that run in the browser and have excellent debugging capabilities not available in the real hardware. I’ve programmed on dozens of CPUs, and they are all pretty similar. Given the oddness of the 1802, I might not recommend it even though I love it myself. It is, on the other hand, very simple to learn. The PDP-8 or PDP-11 are other good candidates, although some of how minicomputers do things are rarely seen today.
Or, pick a machine that doesn’t exist. Most of these were made for learning, so that’s a plus, and many of them also have modern emulators. If you were to pick one, I’d suggest Mix. The books from Knuth are classic and use Mix. They influenced everyone, so you’ll see echoes of Knuth’s ideas in every computer system you ever touch. (That isn’t a quantum computer, at least.)
Just don’t go too far back. Programming the EDSAC, TUTAC, or the 4004 is probably not representative of modern computing at all. Honestly, none of these CPUs are. But they can help set the stage for tackling more advanced processors if needed. Like the old adage: You have to crawl before you walk, and walk before you run.
The Case for Late
You could easily argue the other side, too. Maybe assembly language makes more sense once you understand why you need pointers to make linked lists and why conditional jumping is a thing. If you’ve been programming for a while, some ideas like hex numbers and addresses might already be familiar.
Probably the wrong time to learn it, though, is when you have an intractable bug, and you suspect the compiler is optimizing your code incorrectly. Or at the midnight hour before a deadline when you need to shave that extra little bit from your code.
What Do You Think?
This is, after all, “Ask Hackaday,” so tell us what you think in the comments. Make your case for why no one needs to learn assembly. Or tell us your opinion about the best processor to learn. Learn in the browser? We don’t suggest WebAssembly, but maybe you disagree. What are the best online resources and books? What’s your favorite story about that time that knowing assembly saved the day?
(Digital rain effect from [Rezmason]’s generator.)
Assembly, or it’s close sibling- machine language is extremely valuable, because it teaches how the hardware works, not just the language and software.
You must under registers, logical operations etc – all needed to get the best out of a system.
Assembler was the second language that I learned. In my freshman engineering class at the University of South Carolina, we elected to use the department’s DEC PDP-8. We learned FOCAL, a Dartmouth BASIC clone, in the first class. We learned the PDP-8 assembly language in the following class. I know the assembly languages of the DEC PDP-11, Intel 8080/8085, Motorola 68000, and IBM 360/370.
These days I write code in bash because my employer took away the Python & Java off my system. As a network micro-services tester I am supposed to not need programming languages to automate things ( :-/ ). But I when I started in EET (before Apple) I learned Fortran, then BASIC then 8085 hex then 6502 and then C & Moto 68*. Most of the stuff I write now depends on the system But it’s a mix of asm (Z80, 8085, x86, but mostly 68* asm), C, Python, bash, & JS. I know other languages (C#, Perl, etc.) but don’t use them much. Lots of vintage computer stuff. My interests are in vintage embedded systems so lots of reverse engineering.
For most folks today not in the embedded side of things, I say they don’t need asm but it is a useful tool. There are just too many things you need to learn for today’s env. If you’re on the EE side of things, you need asm so you can deal with things down to chip level like timing and chip level initializations and precedence.
You would probably benefit from learning assembler of some sort, learning registers, accumulators, and such. It reveals to you what a computer actually is.
I learned assembly late and I wish I’d gotten the big picture a lot earlier.
That’s also why I made the 65uino – to give newcomers a chance on real hardware for cheap using a simple assembly language.
I started with learning a little 8086 to get my GW-BASIC games blitting to screen faster. I agree modern assembler is quite different, and learning say Z80 is the way to go. Another option is learning for a micro-controller, fun and useful! Assembler for a ATmega328 in your garden variety Arduino UNO is pretty easy.
Low level programming, even basic stand-alone executable programming in a robust language like C, has not been necessary to know for a good 15 years– whether or not one knows these languages and standards, they are now mostly unused in the workplace. Nearly every job opening I see is web and data management. Sure, any engineer should know Assembly ASAP next to a breadboard and a Pi ….
Doing 1-bit music porting in Z80 asm now whilst checking emails and reading this…
80×86 Asm was still being taught in Australian University’s in 1993. Or at least the one I went to.
BEST thing I ever did those six months.
No other higher computer language has that “greatness” that only the asm enthusiasts will ever know.
Y2K (Year 2000). LOST SOURCE CODE-
Spent 3 years reverse-engineering IBM System/390 assembler modules from the binaries. :-)
If you want to get your ears wet with assembler in microcontrollers, plus get some bonus learn-time with commutating parallel processors.( Note: “communitating” is not really “parallel” in real-time but nevertheless an important concept in modern programmable logic system design using IP/FOSS cores.) Try playing around with the Parallax Propeller-I. A uniques and very interesting misunderstood (arguably) multi-core chip.
The Parallax Propeller-I has an easy to use interpreted language (SPIN) available to get you started. SPIN is kind’a slow but very new-user friendly with lots of examples. Then you can move on to Propeller Assembler (PASM) which is much faster (not blazing fast because it’s not RISC). There are eight commutating cores for you to use via a “hub”. PASM is cycle-synchronous in terms of the number of clock “ticks” as explained in the excellent documentation. But be careful to include the hub commutation time, which in many applications that involves human interface (by no mean all) really does not really matter.
The documentation is strong, and downloadable are pretty-much all in one place.[1] There is excellent community support with good tolerance for beginners. None of the development tools (all are free by the way) are in any way Eclipse encumbered.
The Propeller-I chip is available in a 40-pin PDIP package (amazing today).[2] It is not cheap (about $12 bucks unit quantity), but I think it’s worth it for small-scale or specialized projects. The Propeller-I has a strong following in the creative-arts Film and Prop-Makng industry. But these days, these Marxist movie people are trying to put themselves out of business. (waddya think; yes or no)?
Years ago I was able to wire-wrap my first Propeller-I dev-board clone in an afternoon, complete with an on-board USB-UART programmer.
The Parallax Propeller-I is a chip that deserves more love in the hacker and maker communities. But perhaps it emerged too early when being more “Open” was more important as a political thing.
Relax, Parallax is OK in this respect. Yes, the chip is proprietary (like most chips today), but the software and documentation is as “Open” as anyone will need and the supporting community is strong and the excellent Parallax support is always there.
Let’s get this out of the way: I do NOT work for Parallax or any it’s authorized distributors. No connection. I am just a Parallax Propeller-I product user with a decent amount of time working with this thing. No money is involved as of this date.
1. Propeller-I Documentation
https://www.parallax.com/download/propeller-1-documentation/
2. Propeller 1 Chip – 40-Pin DIP Chip SKU P8X32A-D40 Qty.-1 $11.19 ea.
https://www.parallax.com/product/propeller-1-chip-40-pin-dip-chip/
To create a compilator / interpreter and/or a linker, you definitely will need to know an assembler of the relevant CPU. So, knowing assembler first/early is a must. In all other cases it depends of many factors. BUT, TRUE programers are always hungry to learn a new programming language, being it an assembler, high level (of abstraction), or just a kind of Copilot.
AND it is not so easy to learn an assembler. Even a kid can be reached to draw a line on the screen, but to learn an assembler, you must learn first or in parallel the CPU architecture, what needs some degree of abstract thinking mental capability, which on its side is not the capability the (all) kids have in a lot of (some people never develop such 😄).
I studied x86 (dis)assembly at +HCU’s night classes. SoftICE was like black magic at the time, was sad it didn’t get ported to newer Windows (post NT4/Win2000?).
Provided a good understanding of assembly and how instructions and registers worked.
Assembler is one way of writing machine language.
Compilers which compile into machine language a better option than a 1960s technology assembler?
gcc c transparent portable [ARM m and a, risc-v, x86, mips, avr …] a better solution to writing machine language than an assembler in 2023?
figForth C, and , constructs can be used to write machine code in a high-level language?
Because of the intelligent commentary, this “Ask Hackaday” is on my short list of all time favorite Hackaday posts. It’s wonderful to read good advice that not always agrees, but in every case yields food for thought.
Thanks to all!
An easy way to play with Assembly language is to simply write “C” code and enable keeping the assembly language output from gcc by using “-S”.
https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-c-c-source-in-gcc
Assembly is useful for extreme optimization and especially for writing Drivers.
Writing in “C” in a style that is similar to Assembly and keeping the “C” source as comments in the assembly language output (using “-fverbose-asm”) is also available.
Don’t have a compiler or using a Cellphone, try here: https://gcc.godbolt.org/
Back in primary school, I tried Comal-80. Moving on to High School and MCS51 Assembler, I hit a snag : our teacher couldn’t explain the purpose of programming a micro controller (in the 1990s)..
At university, we started on 8088 assembler and C/C++, when another student decided to steal my assignments (code) and hand in as his own. That passed me off, so I wrote (and linked all of my assignments with) a tiny library, which displayed a message on the CRT: “This code has been written by Henrik xxxxx, student number xxxx. Please insert disk labeled zzzz in 30 seconds or the computer will reboot. Track 0 has been deleted from the main hard-drive and moved to RAM”. He got caught and kicked out (also the harddisk got replaced).
Final step is C# (python off course for R and automation, plus a bit of PowerShell)… but my heart beats for C/C++ and embedded systems.
What about TIS-100 by Zachtronics (Game on steam, really good for assembly)
Also, for learning, Little Man Computer by Peter Higgson
I wouldn’t think much of a CS grad who hasn’t had at least one comp org course with at least a hypothetical assembly language, and anyone with an op systems capstone should have authored a fair amount of asm for that.
I have never successfully written an assembly language program not that I didn’t try.
I started with BASIC on an Altair as a young teen. I tried on it and on a first gen IBM PC when it first came out. I never had decent tools IDE or whatever.
The performance on those early machines was so poor and language options likewise limited. At the time if you wanted speed and complete control it had to be assembly.
These days you have tons of options.
So no you didn’t need to. These days even on a microcontroller you’re better off using C. The compiler knows more than you.
Depending on what you do or want to do understanding assembly might make a ton of sense. But writing new code in it? Nope.
All these responses tell me is that most, if not all, of these commentators are over 60. As far as the question is concerned, it’s a little difficult to answer and depends on why you want or need to learn assembly to begin with. But what I can tell you is if you do want/need to learn assembly, you just might be on your own because very few colleges even teach it anymore.
Deciding which processor to teach.
Funny to have seen Mecrisp in the comments, because I just thought that to start assembly language, the best way for me seems to go through a Forth system and create its words in machine language.
Glad you got into touch with assembly using my Forth! My comment was more on which architecture I recommend when going the direct route. By the way, which one did you choose? My family of Forth compilers supports MSP430, ARM, MIPS, RISC-V and a custom stack processor on FPGA, and there are large differences between these archs in being beginner friendly (or not).
Thanks for the reply. I chose RISC-V. I have to adapt the custom stack processor to my Sipeed Tang FPGA. And finally, I’m waiting a RP2040 Mecrisp Forth – or maybe a Microbit v2 version – — or perhaps a Sony Spresense version — so I could dip in the ARM pool.
Good choice with RISC-V! No need to wait for a RP2040 implementation – just download a copy of current Mecrisp-Stellaris today and have fun!
“issues with CPUs that do out-of-order execution”… You really got me on this one. I really have no clue here…. Got an example?
I missed the discussion, and the comment is at the bottom, but I think what’s missing is the context for learning assembly. I agree with everyone that it should be learned, and be learned early, but with proper context surrounding it. You aren’t learning assembly to write large programs. That should be obvious, but so many people missed the point when I took it. Instead, they “had no idea why they were being forced to take it”. Context is everything.
The first point needs to be the hook, and the one that really makes you understand why you’re learning it. What is that point? To understand the hardware underneath the code, to understand the consequences of, language choice, bad programming practices, security (or lack thereof), performance, and more. All of which are related to the hardware, and become much more obvious when looking at assembly code.
Second point: To understand hardware limitations
Third point: To understand compiler/language limitations.
Nowhere did I mention writing programs, or even optimization of programs (though, the optimization becomes obvious with a good understanding of the hardware – and knowledge of how various generations of the same ISA processors differ helps understand why optimizing compilers can only do so much, and why a human with full knowledge of the targetted hardware – beyond the ISA, can still beat most optimizing compilers!). So with they why, now you can get to the business of understanding what’s going on.
I’ll also say, learning assembly really gave me a good understanding of pointers. It was being forced to use them. I think it was like chapter 5 where my C++ books introduced the concept with useless examples. Of course, experience brings more knowledge, and of course, programming without pointers in C++ is quite limiting (no dynamic allocation for example), it was how it was taught – lacking context – to bring it back to my main point, that I had issue with. Its the same with many subjects. We teach subjects without context far too often, which is what leads to the grumbling “when will I ever need this” line. We all know that as we learn, the context for many of these things becomes more clear, but why not start with the context?? Its almost like we force people to learn the what without the why as hazing, and just like hazing, we do it to the next generation. I know that many “improvements” in any subject/field can end up making things worse, and that’s how these things get rooted so deeply, but its hard to see how teaching with context would decrease performance of students.
So that’s my soapbox for the day :)
Learn about CPUs, rather than assembly. Learn what translates into efficient code and what just makes things hard to read. But don’t try to live in assembly unless you’re working with microcontrollers all day, and maybe not even then if you can do a good job in C and rarely need to write something more optimal.
Back in the DEC VMS days, I would port COBAL applications to VMS, have the compiler output assembler to help optimize performance. Using this I leaned the Big VAX systems supported packed decimal in hardware, but the micro VAX systems emulated it in software, made a big performance hit running COBAL on the Micro VAX unless you changed the data types
I was born in 87, remember playing a little bit with basic on the spectrum of my cousin, but my first “real” experience programming was the TI-Basic for the TI calculators, then i started stealing the Visual Basic books from my cousin ( which was studing computer eng at that moment) i learnt VB4 VB5 and VB6 get a little bit of the early days of .NET and hated it.
Then i got to college learn Java, discover that college was not for me so go out of college but still wanted to go to a carrear as a programer so self taught myself PHP because open source and looked cool.
15years later working mostly with PHP but dabbling with a lot of languages like C# , Swift, Objective-C etc
Tried golang a couple of years ago but it didnt stick, got for Rust this year and it kinda stick, now im also playing with Assembly and mostly turning PHP code into high performance PHP with the knowledge i acquired mostly from Rust but also from Assembly.
In 1965 I tried to learn assembly language on an IBM 1620 computer, but the teacher jumped into flags and loops without introducing any basic information about computer architecture and software. In grad school I programmed a DEC PDP-8/L minicomputer in assembly language and then moved on to an Intel 8008 microprocessor. I wrote a lot of assembly language for many 8-bit MCUs, and a few 16-bit devices. Today the Parallax Propeller II MCU provides good assembly-language tools that let programmers tackle difficult problems. If you need to get “close” to the silicon, assembly language is the way to go. C would be my next choice.
This is a great way to learn. https://bradsprojects.com/digirule2/
I miss all the old computers.
Low level assembly language is fast and reliable. It does what is says on the tin.
My Valve.Computer used a simple PONG game to demonstrate why I built it, to the many who said, WHY?
I also had great fun with a moon lander and the accompanying sounds of a rattling relay. Just like the real thing!
Low level coding [if that’s the correct term] is simply fun.
Please have a look at the technical page of Valve.Computer if you are interested.
I learned first hpl and basic on HP computers, then PDP11 assembly then moved to CDP1C9802, 68XX, 808X assembly language for my job because structured languages where not so much available at this time, except Intel’s one.
I have to say that learning structured languages 1st greatly helped me to structure my programs, because when you face several hundred Ks of assembly language, you MUST organize your code to make it really effective, debuggable and maintainable.
I still have in memory 808X mnemonics in Hex anyway.
I’m an old Cobol guy, and in school we took a Technical Cobol course that consisted of learning enough 360 assembly to read and understand a core dump in order to debug one’s program. In doing so, although I couldn’t have written a 360 assembly program, I learned a lot about how CPUs work and why things happened that affect a program. From that experience, I have always thought it was important and useful for programmers to understand assembly even after I moved on to C/C++ and other languages.
I know this is a necropost, but I wanna say something.
I started in 1988 with a VIC-20. Basic. I loved it.
In 1995, I got a PC. i386.
A good old DX/50.
Microsoft basic was SLOW!
Impossibly so.
That is when I learned assembly. For the i386.
Self taught, in 1996, this was a well earned skill.
But! After about a year of study and practice, I was making my own inline assembly subroutines for Qbasic.
The things I can do with a DX/50 would shock you.
That said, assembly is for PROS ONLY.
I never learned another CPU. It was way too much work to have to do every year when a new architecture comes out.
I loved it when I used it, but it was always too complex.
I would never learn a new CPU today.
Let someone else do the work of optimizing my CPU.
I don’t have a need to put 100% of my processor’s horsepower directly on the screen.
Processor’s are hella powerful today.
Python has been plenty fast for anything I have tried to do.
And I learned it in about half a year.
Self taught in my spare time.
You couldn’t memorize the Ryzen’s instruction set in 6 months. You would have to be a memory master.
I don’t know. Assembly is certainly useful, but not for most use cases. For me, anyway.
TL:DR.
But thanks if you did.
I want to learn for hacking, the only reason.