Assembly is a program in small steps
Assembly language is the readable form of the instructions a processor runs, one small step on each line.
You do not need to write it to use it. Knowing a handful of instructions is enough to see where a program compares two things and what it does next.
By the end of this lesson
Note
I can read a few lines of x86-64 assembly.
Key words
| Word | What it means | Example |
|---|---|---|
| Instruction | one step the processor carries out | |
| Mnemonic | the short name of an instruction | mov |
| Operand | a value or place an instruction works on | |
| Register | a tiny store inside the processor | rax |
| Flag | a one-bit result the processor remembers | |
| Jump | an instruction that moves to another line |
The cells students fill in are left blank in this preview.
An instruction is a name and its operands
Each line is one instruction: a mnemonic and then its operands. In Intel style the place that gets the answer comes first.
mov eax, 5 copies 5 into the register eax. The table reads five instructions the way you will meet them. A register is a tiny store inside the processor, with a name.
Worked example: five instructions
| Instruction | What it does | eax afterwards, starting at 0 |
|---|---|---|
| mov eax, 5 | Copies 5 into eax | 5 |
| add eax, 3 | Adds 3 to eax | 8 |
| sub eax, 2 | Takes 2 from eax | 6 |
| xor eax, eax | Sets every bit of eax to 0 by xor with itself | 0 |
| cmp eax, 8 | Compares eax with 8 and changes no register | 0 |
The cells students fill in are left blank in this preview.
Compare sets a flag, jump reads it
cmp a, b works out the difference and throws the answer away. It keeps only flags, such as "the two were equal".
A jump then reads a flag. je jumps when the two were equal, and jne jumps when they were not. test eax, eax is a quick way to ask whether eax is zero. With no compare in front, a jump has nothing to decide on.
The registers you meet most
| Name | What it usually holds |
|---|---|
| rax, eax | The answer a function gives back |
| rdi | The first argument of a call |
| rsi | The second argument of a call |
| rsp | The top of the stack |
| rbp | The base of the current function's stack |
| rip | The address of the next instruction |
The cells students fill in are left blank in this preview.
Write the practice program again
printf '#include <stdio.h>\n#include <string.h>\nint main(int argc, char **argv) {\n if (argc != 2) { puts("usage: vault WORD"); return 2; }\n if (strcmp(argv[1], "blue-harbour") == 0) { puts("Door open."); return 0; }\n puts("Door shut.");\n return 1;\n}\n' > vault.cShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Compile it
gcc -O0 -no-pie -fno-stack-protector -o vault vault.cShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The part of main that compares
cmp DWORD PTR [rbp-0x4],0x2
je main+0x2f
mov rax,QWORD PTR [rbp-0x10]
add rax,0x8
mov rax,QWORD PTR [rax]
lea rdx,[rip+0xe7f]
mov rsi,rdx
mov rdi,rax
call strcmp@plt
test eax,eax
jne main+0x66Reading the comparison in words
This is a real excerpt from main of our practice program vault, with the addresses left out. It is an example of what you will see.
The first two lines check that one word was typed after the program's own name. Then rdi and rsi are filled and strcmp is called. It leaves its answer in eax: zero means the strings are equal. test eax, eax checks for zero, and jne jumps away when it is not zero.
The compares and jumps in main
objdump -d vault --disassemble=main -M intel | grep -E "[[:space:]](cmp|test|jne|je)[[:space:]]"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
What comes straight after the strcmp call
objdump -d vault --disassemble=main -M intel | grep -A1 "strcmp@plt"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people read assembly like a story, from the top line to the bottom. A jump moves somewhere else, and a conditional jump only moves when the flags say so. Follow the jumps as well as the lines, or you read code that never runs.