On the Value of Assembly Language, and Resources to get you started in Digital Logic, Computer Architecture, and Assembly Language programming.
Despite advances in programming technologies since the 1970s, there are still reasons to understand and learn assembly language programming. Contrary to what one may imagine, Assembly Language is not a relic of the past, even though a typical applications programmer will almost never need to drop into assembly.
In this article, we’ll look at practical situations in embedded systems development in which assembly language programming is still used, pedagogical reasons to learn assembly language, and provide resources and projects for gaining a working knowledge of digital logic, computer architecture, and assembly language programming.
Learning for Embedded Systems Development
Despite advances in programming technologies since the 1970s, there are still reasons to understand and learn assembly language programming. Contrary to what one may imagine, Assembly Language is not a relic of the past, even though a typical applications programmer will almost never need to drop into assembly. Certainly assembly language is NOT recommended for writing general applications software or graphical user interfaces. Yet a decent understanding of assembly language is important both practically in embedded systems development, as well as for developing a solid general understanding of computer engineering, the underpinnings of the software development toolchain (compilers, assemblers, linkers, loaders, debuggers, and so on), and in the analysis and implementation of algorithms.1
The transition to embedded systems development is difficult without a reasonable understanding of assembly language and computer architecture. As embedded computing enters almost every aspect of the modern technology landscape, from intelligent gadgets of all kinds to remote and autonomous systems, not having this knowledge becomes a fundamental impediment to seeing and being able to seize the many opportunities for participating in this interesting and rapidly expanding area.
(I.) Practical reasons for understanding Assembly Language programming
There are at least four practical situations in embedded systems development, in which assembly language programming cannot always be entirely avoided:
- when developing for platforms that do not have C compilers — and these do exist — assembly language becomes, in most cases, the programming interface. The popular Microchip PIC microcontrollers used to be without a targeting C compiler for many years, in part because of the idiosyncratic PIC architecture and the absence of facilities (like a deeply nestable parameter stack) that general compilers require. With their low cost (many under $3.00) and extensive array of built-in peripherals, incorporating these powerful microcontrollers was often done using assembly language programming.2
- when systems require hard real-time performance in the absence of a real-time operating system (RTOS), assembly language on a RISC platform allows interacting directly with the silicon and being able to obtain accurate timing characteristics by counting instructions. This is one of the advantages of the RISC (reduced instruction set computing) architecture — it is a simplified architecture in which each instruction takes a fixed and uniform time for the CPU to execute.
- when writing device drivers or obtaining peripheral access in the absence of an operating system that provides this functionality, or when writing drivers for an operating system.
- when it is required to directly supervise the storage of values to specific registers or the use of specific elements of an underlying CPU architecture, C is often unable to help. Being able to drop into assembly, either inline or through functions, is then the most direct method of access.
This is not to say that the disadvantages of assembly language programming are any the less — assembly language is not portable and almost always has higher overhead when coding, debugging, and maintaining. But in these few areas of embedded systems development, the benefits occasionally outweigh the trade-offs.
It should also be clear that none of these four conditions is ordinarily encountered by a typical applications software engineer. Indeed, these conditions do not always arise in embedded systems development either, especially if the embedded development is done atop an OS or RTOS sitting on a computing platform for which there is a quality C compiler.
So the question remains: for the large number of programmers and engineers for whom the practical reasons are unlikely to materialize, is it useful to learn an assembly language?
(II.) Pedagogical advantages of learning assembly language
Programming in Assembly Language requires a non-trivial understanding of the innards of digital systems and software toolsets. It provides a fruitful hands-on context within which to acquire and exercise this understanding. Compared to higher level languages, assembly language programming requires greater understanding of the following:
- digital logic and digital circuit concepts
- computer architecture: register, bus, memory, the instruction cycle
- microprocessor organization: opcodes, characteristics (timing, organization, peripherals)
- hexadecimal, binary, and decimal numbers and how to use them
- memory access and pointers
- assembler syntax: pseudo ops, directives, syntax, number formats
- calling conventions
- operating system facilities
- the parts of a software toolchain
- linkers and their idiosyncrasies
- loaders, when loading the binary program into memory on a target platform that isn’t the source platform
- using a low-level debugger
Grappling with assembly language programming gives a much better understanding of computing architectures. Once you understand digital circuits and computer architectures, assembly language programming and its toolchain, you will have the working knowledge needed to embark on the road to microcontroller programming and the development of small and medium scale embedded systems applications: reading in sensors (A/D, filters, signal processing), digital I/O, and real-time numerical methods. 3 In addition, the patterns of thought involved in thinking in assembly, and the discipline involved in writing readable code in assembly, are both invaluable in understanding the details that a higher-level optimizing compiler handles “under the hood”.
Recommendations and Learning Resources
The best way to gain a working understanding in the areas discussed above is to do some digital logic design and assembly language coding yourself. The tools are not difficult to acquire and the materials to begin are available for free.
For digital logic and computer architecture, the Digital Works simulator is a simple, freely available, and user-friendly way to get started in digital logic and computer architecture. [Download from Resources]
It is helpful when embarking on learning ventures to identify a defining project that is grand enough to whet your ambitions but is also chosen to guide your learning efficiently through the essential areas you’ll need in order to have a strong working knowledge.
Project (Digital Logic and Computer Architecture)
Design an ALU in hardware to form the heart of a simple calculator. Build up the necessary logic elements using your own ICs that you package up in Digital Logic to be pin-compatible with ICs that you might buy off the shelf.
Excellent IC lists with pinouts are available from GIICM. Datasheets and practical issues like availability and alternatives are available through the DigiKey parameterized product selection index. [See Resources for links].
For assembly language programming, the x86 is an adequate platform for learning the basic techniques, including how to extend assembly language with higher level calls, how to embed assembly language directly into higher level languages, and using all the elements of the software development toolchain: compile, assembler, linker, loader, debugger.
A companion project to the digital logic project above is given below:
Project (Assembly Language)
Develop, in assembly language, computational routines for a simple calculator, including fixed and floating point routines and some basic vector operations (sum, difference, and scalar product).
After getting your feet wet in pure assembly, the way to go here is to migrate into C or Basic (gcc or FreeBasic are two recommended open source packages) and learn how to embed assembly language into higher level languages.
MicroASM is a simple, freely available, and user-friendly way to get started with assembly language programming, after which migrating to NASM, gas, gcc, and the other elements of an open source toolchain is next. [Download from Resources]
Once this understanding has been obtained, assembly should be viewed as a tool to use when it is practically needed. In all other cases when a C compiler exists that targets your intended platform, you should be writing in C. Optimized compiler technology has become so good that it is better to let a computer do what it is better at: detailed automatic attention to the placement and organization of assembly code, while your creativity directs the implementation via a higher level language (C or higher).
Two directions then open themselves, one taking the road into computer science: assemblers, compilers, parsers, and higher level languages, and the other taking the road into microcontrollers, sensors, and embedded development.
Related Reading and Resources
- Introduction to PIC Microcontrollers Andrew Kilpatrick provides an excellent practical introduction that will take you down the road into microcontrollers, sensors, and embedded development.
- A Home-Built 4-bit Computer Viktor Toth describes his journey in designing and building, a simple but functional 4-bit computer from low-level electronic components (TTL logic gates.)
- hurling-boulders-assemblyHurling Boulders: Assembly Language Programming
- x86-assembly-toolsetAn Open Source Assembly Language Toolset
Digital Logic & Computer Architecture
- Download Digital Works 2.0 (freeware)
written by D. J. Barker at the University of Teesside.
- Download Digital Works 3.0 (shareware)
- Quick tutorial for Digital Works by Bob Brown of Southern Polytechnic State University
- A license for DW 3.0 can be purchased here — worth it once you start building more intricate bus-based designs.
- Principles of Computer Hardware by Alan Clements, 3rd Ed., 2000, Oxford University Press: an excellent introduction to Digital Logic and Computer Architecture. Incorporates Digital Works in its pedagogy.
- The GIICM: a online, easily browse-able compendium of IC pinouts
- DigiKey’s Parameterized Search Index with PDF Datasheets on all Parts
Assembly Language for x86
- Using Assembly Language for Algorithm Analysis
This is what Knuth does in The Art of Computer Programming, a Tour de Force in the detailed analysis of fundamental problems and methods in computer science, their techniques and complexity analysis. For these analyses, Knuth assumes an ideal machine, MIX (for the 1960s) and MMIX (for the 2000’s) – a RISC style computer. He abstracts away specific details that aren’t relevant to the essence of algorithm complexity — i.e. the number of registers etc.
It is often useful and helpful to taste implementing an algorithm in assembly language. For this to be practical, you need the facilities of disk access, data loading and saving, and display. These are most practically handled by the OS on a modern CPU, so it is easiest to use the OS functionality. It is also easiest to do all of this within a higher level language in which this interaction is usually quite easy. So the best way to proceed is by embedding (inlining) your assembly language implementations within a higher level language such as C/C++ or Basic. ↩
- Microchip PIC18 and dsPIC, Atmel AVR, and Intel 8051 are all families of microcontrollers that have reasonable optimizing compilers available today, a large and helpful user community, and easy pathways to entry level embedded systems projects. ↩
- When you are ready, an inexpensive, RISC based, non-x86 platform for experimentation becomes handy. Microchip PIC, Atmel AVR, and Intel 8051 are all widely used microcontroller platforms worth considering. ↩