Is Assembly Language Still Relevant for Embedded Software Development?
As embedded systems continue to evolve, you might wonder: should I learn assembly language for embedded software development? Learn the answer in this article.
Every year, I teach a course about embedded systems to engineering and computer science students, and I wrestle with the same question each time. Given the wealth of topics relevant to embedded systems, how much emphasis should I place on assembly language?
A single 15-week semester isn’t long enough to accommodate a complete treatment of all relevant topics on the subject of embedded systems. In developing the curriculum for my course, I have tried to prioritize the practice of marketable skills (to some extent), but a university course should also provide more depth than a tech boot camp. Nevertheless, every time we progress to the unit of the course where we revert for a few weeks from C language to assembly language, I approach Google and ask:
“Should I learn assembly language for embedded software development?”
In this article, I'll try to objectively support or refute the typical answers to this question that are found on software development forums and other web outlets. Ultimately, my aim is to help you, the reader, decide whether or not your specific situation warrants learning or teaching how to program in assembly language.
Does Assembly Language Make Debugging Software Easier?
This is theoretically true; however, the debugging advantage afforded by knowing assembly language rarely materializes in practice. Many microcontroller development boards are equipped with in-circuit debuggers (Figure 1), allowing the developer to set breakpoints, pause execution, and run their code line-by-line in their integrated development environment (IDE).
Figure 1. Like many other development boards, the MSP-EXP432P4111 LaunchPad from Texas Instruments (TI) includes an in-circuit debugger.
When the execution is paused, the debugger also allows the user to peek at the contents of the central processing unit (CPU) and peripheral registers for the microcontroller.
The line-by-line execution of code almost always maps to lines in the user’s C code. Though technically a proxy for line-by-line execution of machine code, this allows a developer to sift through their software in search of runtime bugs without ever having to actually look at and interpret the compiler-generated assembly code (Figure 2).
Figure 2. Line-by-line execution of C code in TI Code Composer Studio [click to enlarge].
Despite that, there are certainly cases where a runtime bug has led me to look in the disassembly view of my code (where the IDE maps assembler mnemonics to machine code); however, those instances are extremely infrequent. Furthermore, I can’t remember a time when I looked at the disassembly view and discovered my bug through that process; more often, I discover my error in plain view in my C code after walking away to get coffee and then coming back. My conclusion from personal experience is that the power of assembly language knowledge in debugging embedded software is significantly diminished by the effectiveness of line-by-line in-circuit debugging in C code (Figure 3).
Figure 3. Line-by-line execution of assembly code in disassembly view in TI Code Composer Studio [click to enlarge]
Is Assembly Language Needed For Embedded Development Jobs?
Annually, IEEE Spectrum releases survey results showing the most popular programming languages for that year. This year, 2022, when listed according to job postings, assembly language ranked 30th on the list (behind even Cobol!), while C and C++ ranked 6th and 7th, respectively. These rankings are across all industries, so it’s no surprise that C/C++ should rank so highly and assembly so low. However, sifting through job postings in the realm of embedded software and IoT (Internet-of-Things) device development confirms that C experience is more often listed as a required skill than assembly language.
Despite its lower skill ranking in recent job postings, it can often depend on the specific career path you choose. For example, in offensive and defensive cyberwarfare, assembly language or code can help boost your resume. In an accompanying article to those IEEE Spectrum survey results, it is mentioned that many job listings in cybersecurity and cyberwarfare call for assembly language experience.
This implies that there are careers where assembly language programming is an important skill; though those jobs may not be in embedded systems development. Another web search for jobs in compiler engineering and design, however, reveals an industry where assembly language experience is a must. Novel architectures are being developed every year for specialized purposes such as rendering video, running neural networks, and edge computing. Developers are being hired to write efficient compilers targeted to these architectures and applications.
Furthermore, there are several communities of developers working on open-source compiler tools (ex., Gnu Compiler Collection or the LLVM Project). Assembly experience is required to make meaningful contributions to those projects, too. So, if you are interested in pursuing that type of work, then learning to program in assembly language is not only a good idea, it’s mandatory. However, if you want to get a job in embedded software development, the benefit of learning assembly is more nuanced. You might be better off honing your C skills.
Are Programs Written in Assembly Language Faster and Smaller Than C?
For this answer to carry weight, we must be designing a system with speed or space constraints that are so great that we would sacrifice development time, code portability, and code maintainability to meet them. That is rarely the case. Manufacturers sell devices now with abundant program memory, and processors are so speedy they can run a Python interpreter right on board. Some of these issues can be addressed using assembly language in embedded development and are most easily solved in the device selection stage of hardware design. In other words, if your compiled C code isn’t going to fit or run fast enough, use a bigger or faster device.
Moreover, it’s only partly true that assembly programs are faster than those compiled from C. Compilers are not as inherently inefficient as they once were because it’s in the best interest of the companies creating the compilers—often the chip manufacturers themselves—to distribute the most efficient tool possible. If your compiled code is slow, the bottom line suffers. While it’s possible for a programmer to know little tricks to shave off clock cycles in assembly language, the compiler knows many of its own tricks, and it never forgets to use them. Therefore, even though there are specific cases where writing directly in assembly language produces faster programs than compiled C, the size and speed of available hardware combined with the development tools can nullify these benefits of writing embedded software in assembly language.
Assembly Language Teaches You About Past Microprocessor Programming
Often, to know where the future of electronic design is heading, it's necessary to understand the past. In this case, understanding how microprocessors were programmed in the past can be compelling since I am nostalgic by nature. Plus, I love learning about the history of computing and electronics. However, if a hands-on history lesson is a goal, writing assembly code for an Atmega328P or the ARM core in a Raspberry Pi won’t be nearly as satisfying or authentic as learning to write code for, say, the MOS 6502 (which you can do here). An example device using the MOS 6502 is the Commodore 64, shown in Figure 4.
Figure 4. Commodore 64 is one of the many devices powered by the MOS 6502 microprocessor. Image used courtesy of Evan-Amos on Wikimedia Commons
Of course, if you really want to write assembly for your Raspberry Pi, there are books for that, too (see Raspberry Pi Assembly Language Programming: ARM Processor Coding by Stephen Smith, for example). Learning to program in assembly language for the joy of the experience is a great reason, but programming in assembly language is not common practice in modern embedded software development. And this does not make a compelling reason for an instructor to include assembly language programming in their curriculumn.
Assembly Language Helps Programmers Understand Processors
Finally, the most compelling reason, to me, for learning assembly language is because it allows a programmer to better understand what the processor is actually doing at the lowest level. In my course, I prioritize depth of coverage over quantity of marketable skills. If you want to know what is really going on at every step of execution, learning assembly language is the best way to achieve that goal.
Assembly knowledge also allows you to explore what your compiler does to convert high-level conditional statements and loops in C to machine code. As much grumbling as I witness from students in the process, I know they are gaining a unique understanding of the execution of code that they can only achieve by programming in assembly.
Conclusion—There is No One-size-fits-all Answer
This article gives a fairly comprehensive survey of the reasons given online for learning assembly language, each with its own merits. However, when deciding whether or not to learn or teach assembly language, each person’s specific context, and goals matter. Someone looking to add marketable skills to their resume might be better served by practicing C development for a different microcontroller than they are used to. Another person might be genuinely curious about the topic and therefore motivated to learn something new. There is no harm in that!
I decided to teach assembly language for a few weeks in my embedded systems course because I want students to better understand what a computing device actually does and how that differs from their assumptions based on the code they have written in C. In any case, if you are asking whether or not you should learn assembly language, your own goals and motivations should guide you as you evaluate whether the answers you find are relevant to your decision.
What thoughts do you have regarding the benefits of assembly language? What experiences have you had? Let us know in the comments below.
As a programmer from the late 70’s that started with the 8080 and 6800 series processors using a mix of assembler and other languages, I’d say that the commercial need to code in assembler is very rare and very very specific. The modern C/C++ compilers for embedded or small architecture devices is very efficient for 90% of applications. It’s only down in the device driver, high performance codecs for audio/video that you occasionally need to augment the compiled code with a hand written or hand optimised piece of code. The last time I touched assembly language was in 2007 for a Texas Instruments DSP for a software defined radio, where I needed to squeeze every bit of performance out of the chip. Knowing how assembler works is great and gives you insight but actually coding in that world is somewhat painful. It’s a bit like tweaking a high performance car for that last 10% extra boost. The other thing that needs to be understood is that each Microprocessor manufacture group has it’s own mnemonic language and structure, it’s with it’s own unique quirks. Which can be not unlike how different high level languages such as Java/NodeJS Python and C++ can share similarities but also have their own unique weirdness and require considerable learning investment.
When I started out in this game with PDP8 and Nova in the late 60s and developed my first microprocessor product ca 1973 there was one choice: Assembler. And if you needed it you wrote it, including in my case a floating point arithmetic package. I started out in assembler and got through a whole career of bare metal programming without using a high level language.
But since retiring I have enjoyed learning and using C/C++ (TBH all wrapped up nice and cozy in an Arduino comfort rug). I was familiar with some aspects of OOP, having used it on PCs with VB.NET, but had never done any high level language programming on MCUs.
In the 80s I did one project in particular that needed every trick in the book to get a 2.5MHz Z80 to drive a thermal printer with a 40uS update rate while still carrying on with other stuff. That required some mean and nasty code that no HLL could ever have imagined doing. If I were doing that today, with say a 240MHz ESP32 (my goto choice of platform now) it would probably be a walk in the park with basic bit banging in C and a 40uS interrupt.
As a hobbyist I pay fewer dollars for an ESP32 module today than I used to pay for a Z80 chip in the 80s. The grunt is plentiful and the grunt is cheap.
So this old dog would certainly not be teaching old tricks to the majority of students.