Память и режимы адресации

Урок показывает, как читать и писать память через квадратные скобки и из чего складывается адрес.

Адресация — способ вычислить адрес ячейки памяти прямо в команде, например по базе и индексу.

Регистр против памяти

Когда операнд написан без скобок — это значение (mov rax, rbx копирует число). Когда в квадратных скобках — это обращение к памяти по адресу:

mov rax, rbx        ; rax = значение rbx
mov rax, [rbx]      ; rax = то, что лежит в памяти по адресу rbx
mov [rbx], rax      ; записать rax в память по адресу rbx

Скобки — это «разыменование», как звёздочка *p в C.

Полная формула адреса

x86-64 умеет вычислять адрес по богатой формуле прямо в команде:

  [ база + индекс * масштаб + смещение ]

  масштаб = 1, 2, 4 или 8
  пример:  [rbx + rcx*4 + 8]

Это идеально ложится на доступ к массиву: база — начало массива, индекс — номер элемента, масштаб — размер элемента в байтах. Например, для массива 32-битных чисел [arr + rcx*4] — это arr[rcx].

Размер обращения

Иногда из команды непонятно, сколько байтов читать/писать, и нужно указать явно:

mov byte  [rbx], 5      ; записать 1 байт
mov word  [rbx], 5      ; 2 байта
mov dword [rbx], 5      ; 4 байта
mov qword [rbx], 5      ; 8 байт

Как работает под капотом

Промоделируем доступ к массиву на Python: память — это список байтов, а формула адреса даёт смещение. Возьмём массив 32-битных чисел и достанем элемент по индексу.

arr = [10, 20, 30, 40]   # массив 32-битных чисел (по 4 байта)
base = 0                 # адрес начала (условный)
scale = 4                # размер элемента в байтах
index = 2
addr = base + index * scale   # [arr + index*4]
print("адрес элемента:", addr, "байт")
print("значение arr[2]:", arr[index])

Вывод:

адрес элемента: 8 байт
значение arr[2]: 30

Процессор делает ровно это, но аппаратно: складывает базу, индекс на масштаб и смещение, получает адрес и обращается к памяти за один такт декодирования.

Частые ошибки

  • Забыть скобки. mov rax, rbx и mov rax, [rbx] — совершенно разные действия.
  • Неверный масштаб. Для массива 8-байтных чисел масштаб должен быть 8, иначе попадёте в середину элемента.
  • Не указать размер при записи константы. mov [rbx], 5 неоднозначно — NASM попросит уточнить byte/dword/qword.

Итог

  • Квадратные скобки означают обращение к памяти по адресу (разыменование).
  • Адрес считается по формуле база + индекс*масштаб + смещение.
  • Эта формула напрямую кодирует доступ к элементу массива.
  • Размер обращения при необходимости указывают словами byte/word/dword/qword.
Проверьте себя
1. Чем отличается mov rax, rbx от mov rax, [rbx]?
AНичем, это синонимы
BПервое копирует значение rbx, второе читает память по адресу rbx
CПервое читает память, второе копирует значение
DВторое работает только с .data
2. Какой масштаб нужен для доступа к массиву 32-битных чисел?
A1
B2
C4
D8
3. Как выглядит полная формула вычисления адреса в x86-64?
Aбаза + индекс
Bбаза + индекс*масштаб + смещение
Cтолько смещение
Dиндекс*масштаб