Machine code and assembly language

Machine Code and Assembly Language

Both machine code and assembly language are low-level languages: they are closely tied to the instruction set of a specific processor and require detailed knowledge of the hardware. Unlike high-level languages, they do not abstract away hardware details. Each type of processor has its own instruction set - the complete set of operations that processor can execute. A program written in the machine code of one CPU type will not run on a CPU with a different instruction set.

Despite both being low-level, machine code and assembly language are distinct from each other in important ways. Understanding these differences explains both how computers actually execute programs and why assembly language was developed as an improvement over raw machine code.

Machine Code and Assembly Language Compared

Machine Code

Machine code is the only language a processor can directly execute. Every instruction is represented as a pattern of binary digits (0s and 1s). When a CPU fetches an instruction from memory, it receives binary data - for example, something like 10110000 01100001 - and its circuits decode that pattern to determine what operation to perform.

Key characteristics of machine code:

  • Written entirely in binary (or sometimes represented in hexadecimal for compactness, such as B0 61).
  • Executed directly by the CPU with no translation needed.
  • Extremely fast to execute because there is no intermediate processing step.
  • Almost impossible for humans to write or read directly - a single instruction is just a sequence of binary digits with no obvious meaning.
  • Completely specific to one processor architecture: machine code for an ARM processor will not work on an x86 processor.

Assembly Language

Assembly language represents machine code instructions using short human-readable codes called mnemonics. Each mnemonic corresponds to exactly one machine code instruction - this is called a 1:1 correspondence. For example, a mnemonic such as MOV, ADD, or JMP tells the programmer (and the assembler) precisely which machine code operation to use. Assembly language is as close to the hardware as you can get while still writing something a human can read.

Key characteristics of assembly language:

  • Uses meaningful abbreviations (mnemonics) such as ADD (add two values), SUB (subtract), MOV (move data), and JMP (jump to another instruction).
  • Each assembly instruction translates to exactly one machine code instruction - a 1:1 relationship.
  • Must be converted to machine code by a program called an assembler before the CPU can execute it.
  • Still specific to one processor architecture - assembly written for one CPU will not work on a different type without modification.
  • Commonly used to develop software for embedded systems (microcontrollers in washing machines, medical devices, car engines) and for controlling specific hardware components such as device drivers.

The 1:1 Correspondence

The most important relationship to understand between machine code and assembly language is their one-to-one correspondence. Every assembly language mnemonic translates directly to one specific machine code instruction - no more, no less. This is what makes assembly language a low-level language: it provides human-readable names for binary patterns, but does not group or abstract multiple machine operations as a high-level language does.

Assembly ADD R1, R2 MOV R0, #5 JMP 0x04 Machine code 00000001 00010010 11100011 10100000 11101010 00000100

Each assembly mnemonic maps to exactly one binary machine code instruction.

This is why assembly language is still classified as a low-level language rather than a high-level one. A single line of Python might translate into dozens of machine code instructions; a single line of assembly always translates into exactly one.

 Key Takeaways

  • Machine code is the only language the CPU directly executes. It consists entirely of binary patterns and is specific to one processor architecture.
  • Assembly language uses human-readable mnemonics (e.g. ADD, MOV, JMP) that each correspond to exactly one machine code instruction.
  • The 1:1 correspondence between assembly and machine code is what classifies assembly as a low-level language.
  • Assembly code must be converted to machine code by an assembler before the CPU can execute it.
  • Assembly language is used for embedded systems and direct hardware control, where precise low-level access to the processor is needed.