Skip to content
UnderDunn Courses

Machine Instructions and Registers

How Programs WorkLesson 4 of 775 minutesLab included

A compiler translates C into machine instructions encoded as bytes. Assembly language is the human-readable notation tools use for those instructions. Disassembly works in the opposite direction: it decodes bytes into assembly text, but it does not restore the original variable names, comments, or programmer intent.

Create decision.c:

#include <stdio.h>
int classify(int value) {
if (value > 10) {
return value + 2;
}
return value - 2;
}
int main(void) {
printf("%d\n", classify(12));
return 0;
}

Compile it with optimizations disabled so the output stays easier to follow:

Terminal window
gcc -O0 -g -o decision decision.c
objdump -d -Mintel decision | less

Search inside less by typing /<classify> and pressing Enter. Press q when finished.

An instruction line contains an address, encoded bytes, a mnemonic, and operands. In Intel syntax, common instructions include:

Instruction Useful first interpretation
mov destination, source Copy a value
add destination, source Add into the destination
sub destination, source Subtract from the destination
cmp left, right Compare by setting processor flags
jmp target Continue at another instruction
jle, jg, and relatives Branch when a condition represented by flags is true
call target Transfer control to a function while preserving a return location
ret Return to the saved location

Registers such as rax, rbp, rsp, and rdi are named storage locations in the x86-64 processor. Some names refer to smaller portions of a register: eax is the low 32 bits of rax.

Do not translate every mov into “assignment.” Compilers use moves for arguments, temporary values, saved state, and memory access. Follow where the value came from and where it goes.

Knowledge check

Question 1 of 2

What is disassembly?

Find the comparison with 10, then the conditional branch following it. Record:

  1. Where the function receives or stores value.
  2. Which instruction compares it with 10.
  3. Which branch selects the value + 2 or value - 2 path.
  4. Which register holds the integer return value near ret.

Change the call from classify(12) to classify(8), predict the output, recompile, and compare both behavior and disassembly. A source change may alter data without changing instruction structure.

The number printed at the left of an instruction is where that instruction resides. An operand may itself be an immediate value, register, or memory address. Treating every hexadecimal number as “the address” is a reliable way to become lost.

When taking notes, label numbers by role: instruction address, branch target, constant, register value, or memory address. The labels are conclusions supported by context, not decoration.

You can now reduce a small assembly function to data movement, arithmetic, a comparison, and a control-flow choice. Next we will examine what call and ret require from the stack.