Files
obsidian/Computer Science/Архитектуры/x86_64.md
T
roma-dxunvrs c0b8ac0043
deploy / Pull and Restart (push) Successful in 16s
fix PL, add x86 in CS
2026-09-29 21:49:51 +03:00

6.7 KiB
Raw Blame History

Архитектура

  • 64-битная (процессоры Intel / AMD)
  • Ассемблер: NASM
  • OC: Linux
  • Размеры данных:
    • byte
    • word (два байта)
    • dword (4 байта)
    • qword (8 байт)

Регистры общего назначения

Все 64-битные регистры начинаются с R. Их младшие части можно прочитать отдельно

База

  • RAX (Accumulator) - аккумулятор, возвращаются результаты функций и номера сисколлов
  • RBX (Base) - обычная переменная
  • RCX (Counter) - счетчик циклов, 4-й аргумент функции, уничтожается сисколлом
  • RDX (Data) - данные, 3-й аргумент функции, второе возвращаемое значение, хранит остаток при делении

Индексы и указатели

  • RDI (Destination Index) - 1-й аргумент функции
  • RSI (Source Index) - 2-й аргумент фукнции
  • RSP (Stack Pointer) - указатель вершины стека
  • RBP (Base Pointer) - указатель базы стекового кадра

Новые регистры

  • R8, R9 - 5-й и 6-й аргументы функций
  • R10, R11 - временные
  • R12-R15 - свободные переменные

Имена частей регистров

64 бита (qword) 32 бита (dword) 16 бит (word) 8 бит (byte)
rax eax ax al
rbx ebx bx bl
rcx ecx cx cl
rdx edx dx dl
rdi edi di dil
rsi esi si sil
rsp esp sp spl
rbp ebp bp bpl
r8..15 r8..15d r8..15w r8..15b

Соглашение о вызовах

  1. Аргументы: RDI, RSI, RDX, RCX, R8, R9
  2. Возврат значения: RAX и RDX
  3. Сохранность регистров
    • Caller-saved (портятся при вызове call): RAX, RCX, RDX, RSI, RDI, R8-R11. Обязанность запоминать их - на вызывающем
    • Callee-saved (обязаны остаться неизменными): RBX, RBP, RSP, R12-R15. Обязанность вернуть их в исходное состояние - на функции
  4. Выравнивание стека
    • В момент call значение регистра RSP должно быть кратно 16
    • При входе в функцию стек сдвинут адресом возврата, поэтому RSP % 16 == 8. Перед внутренним call нужно выровнять стек (сделать push или sub rsp, 8)

Самые нужные сисколлы

Все сисколлы тут

Назначение RAX RDI (fd) RSI (buffer) RDX (size) Возврат в RAX
Чтение (sys_read) 0 0 (stdin) Адрес в памяти Кол-во байт Кол-во прочитанных байт (0 = EOF, <0 = ошибка)
Запись (sys_write) 1 1 (stdout) Адрес в памяти Кол-во байт Кол-во записанных байт
Выход (sys_exit) 60 Код возврата - - Процесс завершается

Самые нужные инструкции

Перемещение данных

  • mov A, B - скопировать B в A
  • movzx - скопировать байт B в регистр A и заполнить старшие биты нулями

Математика

  • add A, B / sub A, B - сложение / вычитание A = A +/- B
  • inc A / dec A - инкремент / декремент
  • neg A - A = -A
  • imul A, B - знаковое умножение A = A * B
  • mul B - беззнаковое умножение, умножает RAX на B. Старшая часть результата в RDX, младшая - в RAX (результат - RDX:RAX)
  • div B - беззнаковое деление. Делит RDX:RAX на B. Частное в RAX, остаток в RDX

Логика

  • and, or, not - побитовое И, ИЛИ, НЕ
  • xor A, B - исключающее ИЛИ (xor rax, rax - быстрый способ обнулить регистр)
  • test A, B - побитовое И без сохранения результата (только ставит флаги) - лучший способ проверить регистр на ноль

Ветвление и переходы

  • cmp A, B - сравнивает A и B, ставит флаги
  • jmp метка - безусловный переход
  • je / jne (или jz / jnz) - прыжок, если Z = 1 / Z = 0
  • Дли знаковых чисел
    • jl / jle (Less / Less or Equal) - меньше / меньше или равно
    • jg / jge (Greater / Greater or Equal) - больше / больше или равно
    • js / jns (Sign) - отрицательное / положительное (флаг S)
  • Для беззнаковых чисел:
    • jb / jbe (Below / Below or Equal) - меньше / меньше или равно
    • ja / jae (Above / Above or Equal) - больше / больше или равно
  • Для переполнений
    • jc / jnc (Carry)
    • jo / joc (Overflow)

Работа со стеком

Растет как в БЭВМ (в сторону уменьшения адресов)

  • push A - кладет 8 байт на стек (rsp -= 8, [rsp] = A)
  • pop A - достает 8 байт со стека (A = [rsp], rsp += 8)
  • sub rsp, 24 - выделить буфер на 24 байта
  • add rsp, 24 - освободить буфер