x86-64 Guide Notes

gravatar
By Ranti
 · 
March 10, 2023
 · 
4 min read

PC consists of processor, memory, registers

  • Registers are processor components that hold data and addresses

To execute a programme, the system copies data from the external device into the internal memory. The processor executes the programme's instructions

  • Byte = One-byte integer -> ends with b
  • Word = Two-byte integer -> ends with w
  • Doubleword = Four-byte integer -> ends with l
  • Quadword = Eight-byte integer -> ends with q

The Assembly Programme is divided into 3 sections

  1. Data Section = Declaring initialised data or constants
  2. BSS Section = Declaring variables
  3. Text Section = Has the actual code. Must start with global _start to tell the kernel where the programme's execution is

In Assembly, comments start with ;

Operand Specifiers

  • Imm refers to a constant value, e.g. 0x8048d8e or 48
  • Ex refers to a register, e.g. %rax
  • R[Ex] refers to the value stored in register Ex and
  • M[x] refers to the value stored at memory address x.

Type

Immediate

Register

Memory

Memory

Memory

From

$Imm

Ea

Imm

(Ea)

Imm(Eb, Ei. s)

Operand Value

Imm

R[Ea]

M[Imm]

M[R[Ea]]

M[Imm + R[Eb] + (R[Ei ] x s)]

Name

Immediate

Register

Absolute

Absolute

Scaled index

Type

Immediate

Register

Memory

Memory

Memory

From

$Imm

Ea

Imm

(Ea)

Imm(Eb, Ei. s)

Description

Provide the constant value

Specify the memory address

To specify the registers you want to move from

If you don't know the exact address you are moving from, but you know the relative distance*

*E.g

Address Number

0

1

2

Value Stored

a

b

c

$$\text{%rab contains 0}$$ $$\text{%ral contains 1}$$ $$ M[I_{mm} + R[E_b] + (R[Ei] \times s)]$$ $$M[1 + (0 + 1)] + 3(E_b, E_i, 1) === 1 $$

Jump Instructions

  • Like a "go-to" statement
  • To shift execution from the current instruction to some other instruction in the code

Register Usage

  • %rax, %rcx, %rdx, %rdi, rsi, %rsp, %r8-r11 caller-save registers are not necessarily saved across function calls
  • %rax is used to store a function's return value, if there is a return value and it is no larger than 64 bits. Otherwise larger return types like structs are returned using the stack
  • %rbx, %rbp, %r12-r15 are callee-saved registers, so they are saved across function calls
    • So when you are moving from one function to another function the values stored in these functions are retained
  • %rsp is used as the stack pointer, a pointer to the topmost element in the stack
    • It points to the next instrucction that needs to be executed
    • This is important because programmes that have code that switch between functions and go inside loops so you need to store the next instruction to be executed
    • Flag registers are used to store the data related to the flag for where the stack pointer is pointing to
  • %rdi, %rsi, %rdx, %rcx, %r8, %r9 are used to pass the first 6 integer or pointer parameters to called functions (used to pass parameters from the caller functions to the callee function)

C code

#include <stdio.h>
int main() {
    int x = 3;
    int y = 4;
    if(x > y) {
        x++;
    }
    else {
        y++;
    }
    return 0;
}
C

Assembly Code

.file "sample.c"
.text
.global main
.type main, @function
main:
; initial ebp and esp commands
  movl $3, %eax ;moving 3 into %eax registers
  movl $4, %ebx ;moving 4 into %ebx registers
  cmpl %ebx, %eax ; (3-4 = -1) comparing the contents of the registers & storing it in a flag register 
  jle .L2 ; jump to L2 if less than or equal to
  addl $1, %eax ; else statement part 1
  jmp .L3 ; else statement part 2
  .L2:
  addl $1, %ebx
  .L3:
  movl $0, %eax ; for return statement
  ret
  
  .size main, .-main
  .ident "GCC: Ubuntu 7.4.0-1ubuntul~18.04.1) 7.4.0"
  .section .note.GNU-stack, "", @progbits
ASM


#include <stdio.h>

int main() {
    int x = 3;
    while(x >= 0) {
        printf("%d\n", x);
        x--;
    }
    return 0;
}
C
.file "sample2.c"
.text
.section .rodata.str1.1, "aMS", @progbits, 1
.LCO:
    .string "%d\n"
main:
    movl $3, %ebx
    jmp .L2
.L3:
    call printf # uses .LCO performs the printf() call
    subl $1, %ebx # 3-1 = 2 in %ebx
.L2: # while loop part 1
    cmpl $0, %ebx # if the result of the comparison is NOT zero go to l3; while loop part 2
    # After jumping to .L3 when we return to -L2 we start again from the top at "cmpl..."
    jns .L3 # while loop part 3
    movl $0, %eax # For return statement; %eax is return register
ret
    .size main, .-main
    .ident "GCC: Ubuntu 7.4.0-1ubuntul~18.04.1) 7.4.0"
    .section .note.GNU-stack, "", @progbits
    
ASM
  • The way jump works is that if you are in instruction 3 and you jump to instruction 5 the next instruction to be executed is instruction 6 not instruction 4
  • All the loops can be implemented in terms of labels, jumps and comparisons
    • Where you compare something and you keep looping through the labels until the comparison result is not as expected and you continue to the next part
View