How CPUs Process Instructions


I’m diving into the realm of Assembly Programming in my spare time, because I’ve had an interest in truly low-level code for a while, now. I’d like to develop a deeper understand of how all this tech around me operates at the base level, and I hear it really helps with cybersecurity, too.
Here’s a simple example of assembly code for the x86 architecture to demonstrate how a CPU processes instructions. I'll include comments to explain each step in detail. This example will show a few basic instructions, including loading data into registers, performing arithmetic, and storing the result.
Assembly Code (x86, NASM syntax)
section .data ; Data section: where variables are stored
num1 db 5 ; Define a byte variable 'num1' with value 5
num2 db 10 ; Define a byte variable 'num2' with value 10
section .bss ; Uninitialized data section (not needed for this example)
section .text ; Code section: where executable code is written
global _start ; Entry point for the program (needed for Linux systems)
_start:
; Step 1: Load values into registers
mov al, [num1] ; Load the value of 'num1' (5) into the AL register (8-bit register)
mov bl, [num2] ; Load the value of 'num2' (10) into the BL register (8-bit register)
; Step 2: Perform an addition (CPU processes the instruction)
add al, bl ; Add the value in BL to the value in AL. AL = AL + BL (5 + 10)
; After this instruction, AL = 15 (in decimal)
; Step 3: Store the result (this is not necessary in real programs but shows how to work with memory)
mov [num1], al ; Store the result (15) back into 'num1'
; Step 4: Exit the program (Linux system call to exit)
mov eax, 1 ; The syscall number for exit is 1 in Linux
xor ebx, ebx ; Set exit status to 0 (no errors)
int 0x80 ; Interrupt to call kernel (executes the system call)
Explanation
Loading values into registers:
- The
mov
instructions load the values from memory (variablesnum1
andnum2
) into the CPU’s registers (AL and BL). Registers are very fast storage locations inside the CPU, allowing it to quickly manipulate values.
- The
Executing an addition:
- The
add
instruction tells the CPU to perform arithmetic. It adds the value in thebl
register (10) to the value in theal
register (5). After this operation, the result (15) is stored in theal
register. The CPU handles this by fetching the values from the registers, performing the addition, and updating the result.
- The
Storing the result:
- The result of the addition (15) is moved back into the
num1
variable in memory. This demonstrates how data flows from registers to memory.
- The result of the addition (15) is moved back into the
Exiting the program:
- The program ends with an
exit
system call, which is a process managed by the CPU's instruction execution. Themov
instructions set up the system call, and theint 0x80
instruction triggers it, signaling the CPU to switch from user-mode execution to kernel-mode to exit the program.
- The program ends with an
How the CPU Processes Instructions
Fetch: The CPU fetches the instruction from memory.
Decode: The CPU decodes the instruction to understand what operation to perform (e.g.,
mov
,add
).Execute: The CPU performs the operation (like loading values into registers, adding values, or storing the result).
Write-back: The CPU writes the result to the specified location (register or memory).
Certainly! Here’s the equivalent assembly code for ARM architecture. The logic will be the same, but the syntax and instructions differ since ARM and x86 have different instruction sets.
ARM Assembly Code
.data // Data section: where variables are stored
num1: .byte 5 // Define a byte variable 'num1' with value 5
num2: .byte 10 // Define a byte variable 'num2' with value 10
.text // Code section: where executable code is written
.global _start // Entry point for the program
_start:
// Step 1: Load values into registers
ldrb r0, =num1 // Load the address of 'num1' into register r0
ldrb r1, [r0] // Load the value at the address in r0 (value of 'num1', which is 5) into register r1
ldrb r0, =num2 // Load the address of 'num2' into register r0
ldrb r2, [r0] // Load the value at the address in r0 (value of 'num2', which is 10) into register r2
// Step 2: Perform an addition (CPU processes the instruction)
add r1, r1, r2 // Add the value in r2 (10) to the value in r1 (5). r1 = r1 + r2 (5 + 10)
// After this instruction, r1 = 15
// Step 3: Store the result (this is not necessary in real programs but shows how to work with memory)
ldrb r0, =num1 // Load the address of 'num1' again into r0
strb r1, [r0] // Store the result (15) from r1 back into 'num1'
// Step 4: Exit the program (using a system call)
mov r7, #1 // Load the syscall number for exit (1) into register r7
mov r0, #0 // Load the exit status (0) into register r0 (indicates no errors)
swi 0 // Software interrupt to invoke the syscall (exit the program)
Explanation
Loading values into registers:
ldrb r0, =num1
loads the address ofnum1
into the registerr0
.ldrb r1, [r0]
loads the value at the address inr0
(the value ofnum1
) into ther1
register. The value5
fromnum1
is now inr1
.
Executing an addition:
- The instruction
add r1, r1, r2
tells the CPU to add the value inr2
(which is10
, fromnum2
) to the value inr1
(which is5
, fromnum1
). After the addition,r1
will hold the value15
.
- The instruction
Storing the result:
strb r1, [r0]
stores the result (15) fromr1
back into thenum1
memory location.
Exiting the program:
- The program ends with a software interrupt (
swi 0
), which invokes the system call to exit the program. Registersr7
andr0
are used to specify the system call number (1
for exit) and the exit status (0
).
- The program ends with a software interrupt (
How ARM CPU Processes Instructions
Fetch: The ARM CPU fetches the instructions from memory, one by one.
Decode: The CPU decodes the instructions (like
ldrb
,add
,strb
,swi
) to understand what operations to perform.Execute: The CPU executes the operations. It loads values into registers, performs arithmetic, and stores results back to memory.
Write-back: The result is stored back into memory, and the program ends with a system call.
Conclusion
As shown, we have x86 and ARM CPU architectures, and ARM assembly code demonstrates similar operations as the x86 example, but in the ARM architecture's instruction set. The main idea is the same: understanding how the CPU processes instructions involves loading data, performing operations on it, and storing the result.
That’s it for this post. I think this granular approach will help me greatly in my later programming endeavors. If you find it helpful, feel free to drop a like or comment. I hope to post more in the coming weeks and months as I start learning Assembly. 🤓
Subscribe to my newsletter
Read articles from DAMIAN ROBINSON directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
