Что такое регистр %eiz?


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

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

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

3   51  

3 ответа:

посмотреть почему GCC LEA EIZ?:

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

...

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

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

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

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

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

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