Assembly #1
Assembly #1
Registers
General Purpose registers are small, fast storage locations inside the CPU used for:
• Arithmetic operations
• Data movement
• Loop control
• Function arguments/return values
Example of sizes:
1 mov rax , 0 x 123456 789ABC DEF0
2 ; RAX = 123456789 ABCDEF0
3 ; EAX = 9 ABCDEF0
4 ; ^^^ Writing to EAX zeroes the upper 32 - bits of RAX
5 ; Use XOR reg , reg to Zero registers
6 ; AX = DEF0
7 ; AL = F0
8 ; AH = DE
1
Register Roles & Conventions
Register Common use (x86-64 Linux Systems)
RAX Return value (or accumulator)
RBX Callee-saved register
RCX 4th argument
RDX 3rd argument
RSI 2nd argument
RDI 1st argument
RSP Stack pointer
RBP Base pointer (used in stack frames)
R8-R9 5th & 6th argument
R10-R11 Temporary (caller-saved)
R12-R15 Callee-saved, general use
• RBP/RSP - Never use/trash these unless you know what you’re doing.
2
Dynamic Changes of a Variable’s Value
After a variable has been declared it can be modified dynamically using instructions
like MOV, ADD, and SUB.
The standard method of modifying → move it into a register, modify it, and then
store it back.
Example:
1 section .data
2 myVar dd 10 ; Declare a 32 - bit integer initialized to 10
3
4 section .bss
5 temp resd 1 ; Reserve space for a variable (32 - bit )
6
7 section .text
8 global _start
9
10 _start :
11 mov eax , [ myVar ] ; Load value of myVar into register
12 add eax , 5 ; Increment by 5
13 mov [ myVar ] , eax ; Store the new value back into memory
14
15 ; Exit program
16 mov eax , 60 ; syscall : exit
17 xor edi , edi ; status : 0
18 syscall
3
What about Registers in brackets?
11 ; Examples :
12 mov eax , [ rbp - 4] ; Load a local variable from the stack frame
13 mov eax , [ rsi + rdi *4] ; Access array element at index in RDI
14
15 ; !! If you ever need a value from a variable use brackets !!
4
.rodata Section (Read-Only Data)
The .rodata section stores constants that should never change, such as messages or
mathematical constants.
1 section .rodata
2 pi dq 3 .141592653589793 ; Define a doubel - precision constant
3
Stacking
The stack is managed by RSP/ESP (stack pointer) and grows downward in memory.
1 ; Stack example
2 section .text
3 global _start
4
5 _start :
6 push 5 ; Push integer 5 onto stack
7 push 10 ; Push integer 10 onto stack
8 pop rax ; Pop value (10) into eax
9 pop rbx ; Pop value (5) into ebx
Functions
Functions are similar to labels, but must be called using the call instruction.
Python example:
1 def add (a , b ) :
2 return a + b
3
4 result = add (3 , 4)
Assembly conversion:
1 section .text
2 global _start
3 global add_numbers ; Declare function for external use
4
5 _start :
6 mov edi , 3 ; First argument ( a )
7 mov esi , 4 ; Second argument ( b )
8 call add_numbers ; Call function
9 ; EAX now contains the result (3 + 4)
10
11 ; Exit program
12 mov eax , 60 ; syscall : exit
13 xor edi , edi
14 syscall
15
16 add_numbers :
17 mov eax , edi ; Load first argument
5
18 add eax , esi ; Add second argument
19 ret ; Return result in EAX
If we notice this will not print out the value even though we save it to the return
register, EAX. What we need to do is run the write system call to actually print
to the terminal. We first would need to convert the result into ASCII and then run
a system call to print the resulting ASCII. There are a few methods to do this, all
being a little complex but the general instructions that will satisfy the most use-cases
are below:
This is a lot of work to do every time, let’s create a reusable call statement that we
can compile with.
** I will provide you with a version that can handle signed numbers. **
If-Clause
Let’s look at a simple Python function:
1 def check_number ( n ) :
2 if n > 10:
3 return 1
4 else :
5 return 0
When converting this to ASM there are some points to think about (i.e., what is
involved in this code):
Some other concerns is with jumping in assembly; jumps are usually tested against
flags which are set via the CMP and TEST instructions. Here is the typical use-case
for each:
• Use CMP for comparing values: ==, <, >, loops, conditionals
• Use TEST to check for zero (val == 0) or bit flags without modifying data
** To come to a common coding standard, we will prioritize CMP for this class. **
6
Jump Condition Description
je Zero Flag = 1 Jump if Equal
jne Zero Flag = 0 Jump if Not Equal
jg ZF = 0 and SF = OF Jump if Greater (signed)
jge SF = OF Jump if Greater or Equal (signed)
jl SF != OF Jump if Less (signed)
jle ZF = 1 or SF != OF Jump if Less or Equal (signed)
*jmp N/A Unconditional jump
*call N/A Jump to procedure, save return address
*ret N/A Return from procedure
* means it is an unconditional jump (does not use CMP or TEST, then test flags)
To print directly from the script (full script using ASCII without our print function):
1 section .data
2 result_char db ’0 ’ ; default character ( updated at runtime )
3
4 section .text
5 global _start
6
7 _start :
8 mov edi , 15 ; <-- Change this to test different
values
9 call check_number ; Result returned in EAX -> 0 or 1
10
7
32 mov eax , 1 ; If n > 10 , return 1
33 jmp end_func
34
35 return_zero :
36 mov eax , 0 ; If n <= 10 , return 0
37
38 end_func :
39 ret
Loops in Assembly
Loops in assembly are typically implemented using CMP (compare), JMP (jump),
and LOOP instructions. The most common loop types are: