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

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

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

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


person Summer_More_More_Tea    schedule 31.03.2010    source источник
comment
Вы можете найти sourceware.org/ml/binutils/2009-01/msg00081.html. интересно.   -  person Pascal Cuoq    schedule 31.03.2010


Ответы (3)


См. Почему GCC LEA EIZ ?:

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

...

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

person Sinan Ünür    schedule 31.03.2010
comment
Умные люди :) Спасибо за ответ! таким образом, приведенный выше код является просто более длинной версией nop: P - person Heartinpiece; 02.09.2013
comment
Точнее, это заполнитель для ненужного байта SIB, который кодирует режим адресации без индекса. - person Peter Cordes; 30.06.2018

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

person Andy Ross    schedule 28.08.2012
comment
binutils делает это только для избыточных байтов SIB (т.е. базы, отличной от E/RSP, и без индекса). Он использует (%esp)/(%rsp) вместо (%esp, %eiz, 1). - person Peter Cordes; 30.06.2018
comment
Подходят ли эти входные данные для ассемблера GNU или это только функция дизассемблера? - person Kaz; 05.05.2020

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

Байт SIB (шкала/индекс/база) состоит из трех частей: индекс (регистр, такой как %eax или %ecx, к которому применяется шкала), шкала (степень двойки от 1 до 8, к которой относится регистр индекса). умножается на) и основание (еще один регистр, который добавляется к масштабированному индексу). Это то, что позволяет использовать такие инструкции, как add %al,(%ebx,%ecx,2) (машинный код: 00 04 4b -- код операции, modr/m, sib (обратите внимание, нет регистра %eiz, даже если использовался байт SIB)) (или в синтаксисе Intel «добавить BYTE 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 инструкция.

person user3196531    schedule 15.01.2014
comment
Кстати, причина, по которой ESP не может быть индексом, заключается в том, что (%esp) является гораздо более полезным режимом адресации, чем (%esp, %esp, 1..8). Поскольку вы не можете кодировать base=ESP без байта SIB, вам нужно каким-то образом указать индекс. (Потому что ни для какой базы не требовался бы disp32, и они не хотели требовать disp32=0( , %esp, 1), чтобы сделать адресацию относительно ESP неоправданно дорогой.) - person Peter Cordes; 30.06.2018