Что делает инструкция сборки LEAL?
Я немного смущен различием между
leal -4(%ebp), %eax
и
movl -4(%ebp), %eax
Может кто-нибудь объяснить это мне?
Ответы
Ответ 1
LEA (загружаемый эффективный адрес) просто вычисляет адрес операнда, он фактически не разыскивает его. Большую часть времени он просто выполняет вычисление, например, комбинированное умножение и добавление для, скажем, индексации массива.
В этом случае он делает простое числовое вычитание: leal -4(%ebp), %eax
просто назначает %eax
зарегистрировать значение %ebp - 4
. Это эквивалентно одной инструкции sub
, за исключением того, что sub
требует, чтобы пункт назначения был таким же, как один из источников.
Команда movl
, напротив, обращается к ячейке памяти в %ebp - 4
и сохраняет это значение в %eax
.
Ответ 2
Если вы хотите взглянуть на это с точки зрения другого языка программирования, то:
int var;
[ ... ]
func (var, &var);
оценивает следующий (Linux x86_64) код сборки:
[ ... ]
4: 8b 7c 24 0c mov 0xc(%rsp),%edi
8: 48 8d 74 24 0c lea 0xc(%rsp),%rsi
d: e8 xx xx xx xx callq ... <func>
[ ... ]
Так как %rdi
/%rsi
являются аргументами 1 st/2 nd вы можете видеть, что lea ...
извлекает адрес &var
переменной, а mov ...
загружает/сохраняет значение var
того же самого.
т.е. в сборке использование lea
вместо mov
аналогично использованию оператора address-of &
в C/С++, а не самой (переменной) самой переменной.
lea
имеет гораздо больше возможностей, чем это, но вы явно задали вопрос о различии между ними.
Для иллюстрации: mov
с операндом памяти всегда выполняет доступ к памяти (загрузка или сохранение), в то время как операнд памяти на lea
просто обрабатывается как арифметика указателя - то есть адрес вычисляется и разрешается, но нет доступа к памяти происходит в самой инструкции. Эти два:
lea 1234(%eax, %ebx, 8), %ecx
movl (%ecx), ecx
приводят к следующему:
movl 1234(%eax, %ebx, 8), %ecx
в то время как следующее:
leal (%eax, %eax, 4), %eax
умножает значение в %eax
на пять.
Ответ 3
Обозначает LEA
в синтаксисе Intel, загружает эффективный адрес (long?).
Ответ 4
Оба LEA и MOV могут загружать регистр со смещением в
переменная, например.
MOV также может передавать содержимое места памяти в регистр, LEA
не может.
Оба LEA и MOV могут вычислять "эффективные смещения", которые можно использовать для выполнения
математика гораздо эффективнее