Регистры общего назначения и их части
Урок знакомит с набором регистров 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:
| Имя | Размер | Какие биты |
rax | 64 бита | все |
eax | 32 бита | младшие 32 |
ax | 16 бит | младшие 16 |
al | 8 бит | младшие 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зарезервированы под стек — с ними осторожно.