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

Урок знакомит с набором регистров x86-64 и их «матрёшкой» из частей разного размера.

Регистр общего назначения — ячейка процессора, в которой можно хранить любое целое число или адрес для вычислений.

Шестнадцать рабочих регистров

В x86-64 есть 16 регистров общего назначения по 64 бита. У части из них исторические имена, у части — просто номера:

  rax  rbx  rcx  rdx        исторические (accumulator, base, counter, data)
  rsi  rdi                  индексы источника и приёмника
  rbp  rsp                  указатели кадра и вершины стека
  r8  r9  r10  r11          добавлены в 64-битном режиме
  r12  r13  r14  r15

Большинство можно использовать как угодно, но у некоторых есть «работа по умолчанию»: rsp — вершина стека, rbp — основание кадра функции. С ними обращаются аккуратно.

Матрёшка из частей

Один и тот же регистр можно трогать целиком или частями. Для rax:

ИмяРазмерКакие биты
rax64 битавсе
eax32 битамладшие 32
ax16 битмладшие 16
al8 битмладшие 8

Эта вложенность нужна для совместимости со старым 16- и 32-битным кодом и чтобы экономно работать с маленькими значениями (например, одним байтом-символом в al).

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

Важная тонкость: запись в 32-битную часть обнуляет старшие 32 бита всего регистра, а запись в 8- или 16-битную — нет. Покажем логику на Python, имитируя 64-битный регистр и его части маской:

MASK64 = (1 << 64) - 1
rax = 0x1111111122222222
# mov eax, 0xAA  -> младшие 32 бита = 0xAA, старшие обнуляются
rax = 0x000000AA
print("after mov eax:", hex(rax))
# mov al, 0xFF   -> меняется только младший байт
rax = (rax & ~0xFF) | 0xFF
print("after mov al :", hex(rax))

Вывод:

after mov eax: 0xaa
after mov al : 0xff

Это частый источник сюрпризов: думаешь, что меняешь «кусочек», а 32-битная запись стирает половину регистра.

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

  • Свободно использовать rsp и rbp как обычные регистры. Они отвечают за стек; испортишь — программа упадёт.
  • Забыть про обнуление старших бит при записи в eax. Это поведение по стандарту, и его важно учитывать.
  • Смешивать размеры в одной команде. Нельзя mov rax, al — операнды должны быть согласованы по ширине (для расширения есть movzx/movsx).

Итог

  • В x86-64 шестнадцать 64-битных регистров общего назначения.
  • Каждый доступен частями: rax/eax/ax/al.
  • Запись в 32-битную часть обнуляет старшие 32 бита, в 8/16-битную — нет.
  • rsp и rbp зарезервированы под стек — с ними осторожно.
Проверьте себя
1. Сколько бит в регистре eax?
A64
B32
C16
D8
2. Что происходит со старшими 32 битами rax при записи в eax?
AСохраняются без изменений
BОбнуляются
CЗаполняются единицами
DКопируются в rbx
3. Какие два регистра отвечают за работу со стеком?
Arax и rbx
Brsi и rdi
Crsp и rbp
Dr14 и r15