Вопрос

В следующем ассемблерном коде, который я выгрузил с помощью objdump:

lea    0x0(%esi,%eiz,1),%esi

Что такое регистрация %eiz?Что означает предыдущий код?

Это было полезно?

Решение

Видишь Почему GCC LEA EIZ?:

По - видимому %eiz является псевдо-регистром, который просто всегда равен нулю (например r0 на MIPS).

...

В конце концов я нашел сообщение из списка рассылки гуру binutils Иэна Ланса Тейлора, в котором содержится ответ.Иногда GCC вставляет инструкции NOP в поток кода, чтобы обеспечить правильное выравнивание и тому подобное.Инструкция NOP занимает один байт, поэтому можно подумать, что вы могли бы просто добавить столько, сколько необходимо.Но, по словам Иэна Ланса Тейлора, чипу быстрее выполнить одну длинную инструкцию, чем множество коротких инструкций.Таким образом, вместо вставки семи NOP-инструкций они вместо этого используют один bizarro LEA, который использует семь байт и семантически эквивалентен NOP.

Другие советы

(Очень поздно для игры, но это показалось интересным дополнением):Это вообще не регистр, это особенность кодировки инструкций Intel.При использовании байта ModRM для загрузки из памяти в поле register используется 3 бита для хранения 8 возможных регистров.Но место, где "был бы" ESP (указатель стека), вместо этого интерпретируется процессором как "байт SIB следует этой инструкции" (т.е.это расширенный режим адресации, а не ссылка на ESP).По причинам, известным только авторам, ассемблер GNU всегда представлял этот "ноль там, где в противном случае был бы регистр" как регистр "%eiz".Синтаксис Intel просто отбрасывает это.

Энди Росс приводит гораздо больше основополагающих рассуждений, но, к сожалению, ошибается или, по крайней мере, вводит в заблуждение относительно технических деталей.Это правда, что эффективное обращение всего лишь (%esp) не может быть закодирован только с помощью байта ModR / M as вместо того, чтобы быть декодированным как (%esp), он используется для сигнализации о том, что также включен байт SIB.Однако, в %eiz псевдорегистр не всегда используется с байтом SIB для представления того, что был использован байт SIB.

Байт SIB (масштаб / индекс / база) состоит из трех частей:индекс (регистр , такой как as %eax или %ecx к которому применяется масштаб), масштаб (степень двойки от 1 до 8, на которую умножается регистр индекса) и базовый (другой регистр, который добавляется к масштабированному индексу).Это то, что позволяет выполнять такие инструкции, как add %al,(%ebx,%ecx,2) (машинный код: 00 04 4b -- код операции, modr /m, sib (обратите внимание, что нет регистра %eiz, даже если использовался байт SIB)) (или в синтаксисе Intel "добавить БАЙТ PTR [ecx*2+ ebx], al").

Однако, %esp не может использоваться в качестве регистра индекса в байте SIB.Вместо того чтобы разрешать эту опцию, Intel добавляет возможность использовать базовый регистр как есть без масштабирования или индексации.Следовательно, чтобы устранить неоднозначность между случаем add %al,(%ecx) (машинный код: 00 01 -- код операции, modr/m) и add %al,(%ecx) (машинный код: 00 04 21 -- код операции, modr/m, sib), альтернативный синтаксис add %al,(%ecx,%eiz,1) вместо этого используется (или для синтаксиса Intel: add BYTE PTR [ecx+eiz*1],al).

И, как объясняется в статье, на которую ссылается Синан, эта конкретная инструкция (lea 0x0(%esi,%eiz,1),%esi) просто используется как многобайтовый nop (эквивалент esi = &*esi) так что вместо нескольких nop-подобных инструкций должна выполняться только одна nop-подобная инструкция.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top