Ассемблер
Инструкция на ассемблере: как понять -12(%rbp)
Запись -12(%rbp) в ассемблере означает обращение к памяти по адресу rbp - 12. Это не само число -12, а смещение от базового регистра rbp. Такая форма часто встречается в AT&T-синтаксисе на Linux, особенно если смотреть код, который сгенерировал GCC
Пример:
movl -12(%rbp), %eax
Читается так: взять 4 байта из памяти по адресу rbp - 12 и положить их в eax
Почему именно rbp
rbp часто используется как base pointer — опорная точка текущего стекового кадра функции. Когда функция начинается, компилятор может сделать примерно такую подготовку:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
Смысл:
- старое значение
rbpсохраняется в стек; rbpстановится опорой текущей функции;rspотодвигается вниз, чтобы освободить место под локальные переменные.
После этого локальные переменные удобно находить по отрицательным смещениям от rbp: -4(%rbp), -8(%rbp), -12(%rbp)
Что означает -12
В записи:
-12(%rbp)
число -12 — это displacement, то есть смещение. Итоговый адрес считается так:
адрес = значение rbp - 12
Если rbp = 0x7fffffffe000, то -12(%rbp) указывает на:
0x7fffffffdff4
По этому адресу лежит какое-то значение: байт, 4 байта, 8 байт. Размер зависит от инструкции
Откуда понять размер
Размер виден по имени инструкции в AT&T-синтаксисе:
movb -12(%rbp), %al
movl -12(%rbp), %eax
movq -16(%rbp), %rax
Суффиксы:
b— 1 байт;w— 2 байта;l— 4 байта;q— 8 байт.
movl -12(%rbp), %eax читает 4 байта. movq -16(%rbp), %rax читает 8 байт
Как это выглядит в Intel-синтаксисе
AT&T:
movl -12(%rbp), %eax
Intel:
mov eax, dword [rbp-12]
Смысл один и тот же: прочитать 4 байта из памяти по адресу rbp - 12
Если вы учитесь по NASM, Intel-синтаксис обычно выглядит понятнее. Если смотрите дизассемблирование GCC или GDB, чаще увидите AT&T-синтаксис
Пример из C
Код:
int main(void) {
int x = 10;
return x;
}
Компилятор может создать похожую логику:
movl $10, -4(%rbp)
movl -4(%rbp), %eax
Первая строка кладет число 10 в локальную переменную на стеке. Вторая строка читает эту переменную в eax, чтобы вернуть результат
Почему бывает -12, а не -4
Компилятор размещает локальные переменные с учетом размеров, выравнивания и временных значений. Поэтому одна переменная может лежать по -4(%rbp), другая по -8(%rbp), третья по -12(%rbp). Число не обязано совпадать с номером переменной
Частые ошибки
Думать, что -12 — это значение переменной
Нет. Это смещение адреса. Значение хранится в памяти по адресу rbp - 12
Путать rbp и rsp
rsp меняется при push/pop и выделении места. rbp часто остается стабильной опорой функции
Не видеть размер операции
movl читает 4 байта, movq читает 8 байт. Смещение само по себе не говорит размер
Смешивать синтаксисы
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- CPI в ассемблере: что делает инструкция
- CMP asm: что делает инструкция сравнения
- CMP в ассемблере
- CMP в ассемблере: как работает сравнение