COA Notes
Introduction to assembly language programming, its relationship to machine code, and why it matters.
Introduction
Assembly language is the thin layer between human-readable code and the raw binary that your CPU actually executes. Every program — whether written in Python, Java, or C++ — eventually becomes assembly instructions before being converted to machine code. Learning assembly is like getting X-ray vision for software: you see exactly what the hardware does, understand why some code is fast and other code is slow, and gain the ability to write programs that operate at the absolute limits of hardware performance.
What Is Assembly Language?
Assembly language is a human-readable representation of machine code where each instruction corresponds to exactly one CPU operation:
One line of C became four assembly instructions and four 32-bit binary words. This is the reality of what the CPU does — there is no magic.
Why Learn Assembly?
1. Understanding Performance
Version B is faster because it reduces loop overhead (fewer branches) and enables instruction-level parallelism. Assembly knowledge makes this obvious.
2. Debugging at the Lowest Level
When your program crashes with a "segmentation fault," understanding assembly lets you:
- Read the crash dump and identify the exact failing instruction
- Understand what the registers contained at the moment of failure
- Recognize buffer overflows, null pointer dereferences, and stack corruption
3. Security and Reverse Engineering
- Malware analysis requires reading assembly (malware is not distributed with source code)
- Exploit development requires understanding instruction-level behavior
- Binary reverse engineering for compatibility or security auditing
4. Embedded Systems
- Many embedded systems are programmed partly in assembly for:
- Boot code (first instructions after power-on)
- Interrupt handlers (time-critical response)
- Hardware initialization (direct register manipulation)
Assembly Language Components
Instructions (Mnemonics)
Human-readable names for CPU operations:
ADD → Addition
SUB → Subtraction
MOV → Move (copy) data
LW → Load Word from memory
SW → Store Word to memory
BEQ → Branch if Equal
JMP → Unconditional JumpOperands
What the instruction operates on:
add $t0, $t1, $t2 ; Register operands
addi $t0, $t1, 42 ; Immediate operand (constant)
lw $t0, 0($sp) ; Memory operand (address)Labels
Named locations in code (resolved to addresses by assembler):
loop_start: ; Label marks this address
add $t0, $t0, $t1
addi $t2, $t2, -1
bne $t2, $zero, loop_start ; Branch back to labelDirectives
Instructions to the assembler (not executed by CPU):
.data ; Following data goes in data segment
msg: .asciiz "Hello" ; Allocate string in memory
arr: .word 1, 2, 3 ; Allocate array of integers
.text ; Following code goes in code segment
.globl main ; Make main visible to linkerComments
; This is a comment (x86 style)
# This is also a comment (MIPS style)The Assembly Process
| ▼ [Assembler | NASM, GAS, MARS] |
| ▼ [Linker | ld, link.exe] |
| ▼ [Loader | OS] |
What the Assembler Does:
- Pass 1: Scans code, builds symbol table (label → address mapping)
- Pass 2: Translates each instruction to binary using opcode tables, resolves labels to addresses
- Output: Object file with machine code + relocation information
Two-Pass Assembly Example:
j end ; Pass 1: address of 'end' unknown!
start: add $t0, $t1, $t2
sub $t3, $t0, $t4
end: nop ; Pass 1 records: end = address 0x0C
; Pass 2: Now knows end = 0x0C, encodes jump targetAssembly vs Machine Code
Assembly is one-to-one with machine code — each mnemonic maps to exactly one binary encoding. This is different from compiling C (one C statement may produce many machine instructions).
Registers: The Assembly Programmer's Variables
In assembly, you work primarily with registers, not named variables:
Register Conventions (MIPS)
| Register | Name | Purpose | Who saves? |
|---|---|---|---|
| $0 | $zero | Always 0 | - |
| $2-$3 | $v0-$v1 | Return values | Caller |
| $4-$7 | $a0-$a3 | Arguments | Caller |
| $8-$15 | $t0-$t7 | Temporaries | Caller |
| $16-$23 | $s0-$s7 | Saved registers | Callee |
| $29 | $sp | Stack pointer | Callee |
| $31 | $ra | Return address | Caller |
Your First Assembly Program
# MIPS: Print "Hello, World!"
.data
message: .asciiz "Hello, World!\n"
.text
.globl main
main:
# Print string
la $a0, message # Load address of string
li $v0, 4 # System call 4 = print string
syscall # Execute system call
# Exit program
li $v0, 10 # System call 10 = exit
syscallEach line does exactly one thing. No hidden operations, no implicit behavior. What you write is exactly what executes.
Key Takeaways
- Assembly language is a one-to-one mapping to machine code — each mnemonic corresponds to exactly one binary instruction
- Programs consist of instructions (operations), operands (data), labels (addresses), and directives (assembler commands)
- Registers are the primary "variables" in assembly — fast, limited, and explicitly managed by the programmer
- The assembler performs two passes: first to build the symbol table, second to generate binary code
- Learning assembly gives you power: performance optimization, low-level debugging, security analysis, and hardware understanding
- Every high-level program eventually becomes assembly — understanding this layer removes the mystery of how software controls hardware
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Assembly Language Introduction.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Computer Organization & Architecture topic.
Search Terms
computer-organization, computer organization & architecture, computer, organization, assembly, language, introduction, assembly language introduction
Related Computer Organization & Architecture Topics