90 lines
6.7 KiB
Markdown
90 lines
6.7 KiB
Markdown
## Архитектура
|
||
- 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)
|
||
## Самые нужные сисколлы
|
||
Все сисколлы [тут](https://gitlab.se.ifmo.ru/programming-languages/cse-programming-languages-fall-2026/main/-/blob/master/docs/system-calls.md)
|
||
|
||
| Назначение | 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` - освободить буфер |