No history yet

Вступ до асемблера

Що таке мова асемблера?

Мова асемблера — це мова програмування низького рівня, яка дуже близька до інструкцій, що їх розуміє процесор комп'ютера. На відміну від мов високого рівня, як-от Python чи Java, які використовують складні команди, асемблер працює з базовими операціями, які процесор виконує безпосередньо.

Уявіть, що ви віддаєте накази безпосередньо солдату, а не генералу, який потім передає їх далі. Асемблер — це розмова із солдатом.

Цей посібник зосереджений на мові асемблера, мові програмування низького рівня, що забезпечує прямий зв'язок з апаратним забезпеченням комп'ютера.

Вивчення асемблера дає змогу зрозуміти, як насправді працює комп'ютер. Це корисно для оптимізації критичних ділянок коду, розробки драйверів або просто для того, щоб стати кращим програмістом.

Структура програми

Програма на асемблері зазвичай складається з кількох секцій. Найважливіші з них — .text, .data та .bss.

  • .text: Тут міститься ваш код — інструкції, які виконуватиме процесор.
  • .data: У цій секції зберігаються ініціалізовані дані, тобто змінні, які мають початкове значення.
  • .bss: Тут оголошуються неініціалізовані дані. Для них просто резервується місце в пам'яті, без початкового значення.
; Програма Hello, world! для Linux x86_64 (синтаксис NASM)

section .data
    msg db 'Hello, world!', 0x0a  ; Наш рядок, 0x0a - символ нового рядка
    len equ $ - msg             ; Довжина рядка

section .text
    global _start

_start:
    ; Системний виклик для виведення на екран (write)
    mov rax, 1                  ; Номер системного виклику (sys_write)
    mov rdi, 1                  ; Файловий дескриптор (1 - stdout)
    mov rsi, msg                ; Вказівник на наше повідомлення
    mov rdx, len                ; Довжина повідомлення
    syscall                     ; Виклик ядра операційної системи

    ; Системний виклик для завершення програми (exit)
    mov rax, 60                 ; Номер системного виклику (sys_exit)
    xor rdi, rdi                ; Код повернення 0 (успішне завершення)
    syscall                     ; Виклик ядра

Цей приклад демонструє базову структуру: ми оголошуємо дані в секції .data та пишемо виконуваний код у секції .text. Точка входу в програму позначена міткою _start.

Регістри та пам'ять

Процесор не працює з даними безпосередньо з оперативної пам'яті (RAM). Спочатку він завантажує їх у спеціальні комірки всередині себе, які називаються регістрами. Регістри — це надзвичайно швидка пам'ять, такий собі робочий стіл процесора.

Lesson image

В архітектурі x86_64 є кілька регістрів загального призначення. Ось основні з них:

РегістрПризначення
RAXАкумулятор; використовується для повернення значень
RBXБазовий регістр; для зберігання даних
RCXЛічильник; часто використовується в циклах
RDXРегістр даних; розширення для RAX
RSIВказівник на джерело (Source Index)
RDIВказівник на приймач (Destination Index)
RSPВказівник стека (Stack Pointer)
RBPВказівник бази стека (Base Pointer)
R8-R15Додаткові регістри загального призначення

Для переміщення даних між регістрами та пам'яттю використовується інструкція mov (від англ. move). Це одна з найпоширеніших команд в асемблері.

mov destination, source

Ця команда копіює значення з source (джерела) в destination (приймач). Наприклад, mov rax, 10 запише число 10 у регістр RAX. Щоб завантажити значення зі змінної в пам'яті, ми використовуємо її ім'я: mov rcx, [my_variable].

Звернення до операційної системи

Програми на асемблері не можуть самостійно виконувати складні дії, як-от виведення тексту на екран чи читання файлу. Для цього вони просять допомоги в операційної системи (ОС). Цей процес називається системним викликом.

Щоб зробити системний виклик, потрібно:

  1. Помістити номер потрібного виклику в регістр RAX.
  2. Помістити аргументи для цього виклику в регістри RDI, RSI, RDX тощо.
  3. Виконати інструкцію syscall.

Інструкція syscall передає керування ядру ОС. Ядро виконує необхідну роботу, а потім повертає керування назад вашій програмі.

У нашому прикладі "Hello, world!" ми робили два системні виклики:

  • sys_write (номер 1 в RAX) для виведення тексту.
  • sys_exit (номер 60 в RAX) для коректного завершення програми.

Тепер, коли ви знаєте основи, час перевірити свої знання.

Quiz Questions 1/5

Що таке мова асемблера?

Quiz Questions 2/5

У якій секції програми на асемблері слід оголошувати змінні, які мають початкове значення (ініціалізовані дані)?

Це лише верхівка айсберга. Асемблер відкриває двері до глибокого розуміння роботи комп'ютера, від оптимізації продуктивності до аналізу зловмисного програмного забезпечення.