When knowing Assembly Language is good

Is it vital to programming to know how the computer works? No…probably not with the high-end applications of today. I have only a vague idea of how WordPress is combining the pieces of this post onto your screen and have never made a study of HTML or PHP. But when you are working with low-end computers, closer to the actual machine operations, it can make a difference.

The technology of all the computers I have known always involved individual instructions. Among these are two categories of computers: Complex Instruction Set Computers (CISC), of which the 8051 family is a member, and Reduced Instruction Set Computers (RISC) which boast of faster execution speeds but require more of their relatively simple instructions to accomplish a given task. With the early microprocessors the CISC instruction set was quite limited…there weren’t very many instructions and they all fit in a single byte. For the 8051 family there are 1, 2 and 3-byte instructions–the first byte is always the actual instruction but the instruction decoder recognizes that some instructions need a second byte (like how far to jump with a short jump) or a third byte (like an absolute jump to a specific 2-byte address). From the start of the 16-bit processors such as the 8086, more complicated instructions were added. By the time you got to the 486 and pentium the size of the machine instruction set was irrelevant to most users because they had moved to high-level languages and never had to deal with them.

As I say in C and the 8051, optimizing is more important to speed when the instructions are in an often-repeated loop. Consuming a few extra instruction cycles once slows things down by a few microseconds, but those same extra cycles in a loop can make a difference of milliseconds which could mean missing some external signal when it arrives. And sometimes when programming in C (or in PL/M in the old days), you can think an expression is doing one thing when it actually does something else. An optimizing C compiler, for example, might load a specific value into a variable. If the compiler notices that variable has been not been altered in subsequent instructions, rather than reading the value back in from memory for a later instruction, it might simply substitute the last written value as a constant and save the bother of the memory fetch. Very clever and efficient, unless that variable is actually a memory-mapped external I/O address or a block of memory shared by two processors. The C language does not normally function in a world where something else impacts the value of a variable.

So here are situations where knowing assembly language can be useful:

  1. Where optimizing code is vital to a loop and the savings is worth the extra time spent in programming.
  2. Where a piece of code is not behaving as expected and it is vital for debugging to know how the compiler chose to carry out the instructions.
  3. Where you have gotten very clever and condensed in your C programming and you need to check that it has not in some way been optimized in an unexpected way.

I consider assembly programming in general obsolete…there are much more efficient ways to generate code that are less error prone and leave the details to the compiler. But when you are programming a microcontroller using interrupts and all the hardware details, having at least a nodding acquaintance with how a computer operates and how machine code does the job is vital.

Related posts: