Assembly Language Programming
Programming back in the 1970s was often done in Assembly Language in order to squeeze maximum power and performance from the much slower computers of that era. I still enjoy Assembly Language Programming today in order to produce tiny apps that are fast and efficient.
Every computer program is a sequence of logical instructions that the computer carries out, such as:
ADD THESE TWO NUMBERS
STORE THE RESULT
QUIT IF THE RESULT IS ZERO
OTHERWISE, PRINT THE TOTAL
The above instructions are something that we humans can understand and follow. For them to be correctly understood and followed by a computer, they must be written in one of the many programming languages suitable for that computer.
There are many different programming languages, like "Basic", "Pascal", "C", "Python", "Java", with varying similarities and differences. Most of these are called "high-level" languages because they take a series of powerful, high-level commands (which are relatively easy for humans to understand) and translate each of them into a series of smaller, low-level processor instructions (which are understood by the computer).
"Assembly Language", on the other hand, is called a "low-level" language – it's like writing in the native tongue of the processor chip. In Assembly Language, the programmer is responsible for writing each and every processor instruction.
Why Use Assembly Language?
Generally speaking, the more "human-readable" the language, the less efficient the resulting program because there will always be some inefficiencies in translation. With Assembly Language, there is no translation, resulting is a more efficient finished program that contains fewer overheads.
Although programming in Assembly Language is more difficult up front, the rewards are reaped over and over again while the program runs. After all, a program is executed many more times than it is written. To me, this is a modern example of the old adage: "The end justifies the means."
Comparing Programming Languages
A simple example that is commonly used to test different programming languages is a program to write the message: "Hello, World", then exit. Let's see this example written in three different programming languages.
NOTE: The following three sample programs can each be downloaded for your testing. They were written for computers running Windows, but may also also be run on Mac OS or Linux using a Windows emulator. Most browsers let you right-click on the name of the program, then choose something like: "Save Target As" to save the program onto your computer.
Language #1 – Basic
In this high level language, the "Hello, World" source code amounts to two simple instructions:
PRINT "Hello, World"
When this program is compiled using Turbo Basic (a Basic complier from the 1980s), the result is a DOS executable program Hello1.exe that is 29,152 bytes in size. That's because the compiler has added to the finished program a whole library of additional functions that are never even used by the program.
Language #2 – Assembly Language (for DOS)
The same "Hello, World" message print function requires many more lines of source code (16 in this example):
ASSUME CS:SEGMT, DS:SEGMT
MOV DX,OFFSET Text
DB "Hello, World$"
Despite the larger source code, the finished result when compiled is a TINY stand-alone DOS executable program Hello2.com of only 25 bytes!
Language #3 – Assembly Language (for 32-bit Windows)
Although this source code is also 16 lines (as above), they're slightly more complicated lines due to the more advanced function calls in Windows:
.MODEL FLAT, STDCALL
MessageBoxA PROTO :DWORD, :DWORD, :DWORD, :DWORD
ExitProcess PROTO :DWORD
Heading DB "Ian's Message Box", 0
Text DB "Hello, World", 0
INVOKE MessageBoxA, 0, OFFSET Text, OFFSET Heading, 0
INVOKE ExitProcess, 0
This compiles to a 1,536 byte Windows executable program Hello3.exe, which displays the "Hello, World" in a simple message box. Although larger than the previous example due to the overhead required by Windows, it's still TINY compared with the megabytes of typical Windows programs!
Despite the fact that Assembly Language can produce the most powerful and efficient programs, the majority of today's software (even Windows itself) in written in high-level programming languages.
Software developers have many reasons for this, some quite legitimate, but mostly to do with maximising profits. The simple truth is that it takes more effort to produce a program using Assembly Language than it does with other languages. As a result, Assembly Language is generally only used on those portions of programs where performance is critical (such as the core functions of Windows).
However, if you look around, you'll find that there are still some dedicated programmers out there writing powerful apps in Assembly Language. In my case, I love the challenge of producing the smallest, most efficient apps that will do the job; the performance gains are part of the reward.
– Ian Fieggen, Sep-2006
Update – Aug-2019
Looking back on this article – written almost 13 years ago – things have changed enormously. Recently I've been writing Android apps, which is worlds apart from assembly language programming. I feel both lost and liberated!
Some recent feedback from a website visitor (see below) also presented several valid counterpoints. You can decide for yourself the merits of using high-level programming languages for today's applications and leaving assembly language in the past.
Upon reading your section on assembly programming I believe you're missing a few key points about programming in assembly vs a high level language, which would make the section more balanced and less in favor of assembly.
What do you think about the following points?
- Most high level programming languages are (extremely) efficient at producing their assembly equivalent during compilation, to the point where writing assembly is discouraged since the compilers will most likely do a better job with few but known limitations.
- Assembly code is harder to maintain than high-level programming languages and will thus more easily retain bugs, since they are harder to test for and fix.
- Assembly (often) requires more lines of code than a high level language will, and we've known the strong positive correlation between the amount of bugs and lines of code in a program. (Made worse due to the previous point)
- Assembly is static, it can't automatically enjoy from improvements such as a higher register count in future processors or more efficient library implementations and it can't run on some different processors (due to cpu-specific instructions) let alone different architectures without modification.
- Raw code execution isnt the bottleneck it used to be in the past. To quote Wikipedia: "increasing processor performance has meant that most CPUs sit idle most of the time, with delays caused by predictable bottlenecks such as cache misses, I/O operations and paging. This has made raw code execution speed a non-issue for many programmers."
I believe that in the default case, assembly should not be used. There is a place for it, a few niche applications even demand it, but it doesn't seem to me to be the better all-round choice for either performance or development.
– Marnick V., Aug-2019