Несколько вопросов о [base + index * scale + disp]

Общая форма адресации памяти в синтаксисе Intel и AT&T следующая:

[base + index*scale + disp]
disp(base, index, scale)

Мои вопросы следующие:

  • Могут ли base и index быть любым регистром?
  • Какие значения могут принимать scale: 1, 2, 4 и 8 (при этом 1 по умолчанию)?
  • Являются ли index и disp взаимозаменяемыми (с той лишь разницей, что index - регистр, а disp - непосредственное значение)?

person Community    schedule 14.01.2015    source источник
comment
По теме: Что означает MOV (% r11,% r12,1),% edx?   -  person Peter Cordes    schedule 07.02.2020
comment
Также несколько примеров режима адресации AT&T в stackoverflow.com/tags/att/info   -  person Peter Cordes    schedule 11.04.2020
comment
В некоторой степени связано: Ссылка на содержимое области памяти. (Режимы адресации x86), чтобы узнать больше о различных подмножествах общей формы и о том, когда их можно использовать.   -  person Peter Cordes    schedule 25.08.2020


Ответы (1)


Это описано в руководстве Intel:

3.7.5 Указание смещения
Смещение в адресе памяти может быть указано непосредственно как статическое значение (называемое смещением) или путем вычисления адреса, состоящего из одного или нескольких из следующих компоненты:

  • Смещение - 8-, 16- или 32-битное значение.
  • База - значение в универсальном регистре.
  • Индекс - значение в универсальном регистре. [не может быть ESP / RSP]
  • Масштабный коэффициент - значение 2, 4 или 8, умноженное на значение индекса.

Смещение, возникающее в результате добавления этих компонентов, называется эффективным адресом.

Масштабный коэффициент кодируется как 2-битный счетчик сдвига (0,1,2,3) для коэффициентов масштабирования 1, 2, 4 или 8. И да, *1 (количество сдвигов = 0) является значением по умолчанию, если вы пишете (%edi, %edx); что эквивалентно (%edi, %edx, 1)


В синтаксисе AT&T это disp(base, index, scale) - константы выходят за рамки скобок. Некоторые ассемблеры синтаксиса Intel также допускают синтаксис типа 1234[ebx], другие - нет. Но синтаксис AT&T жесткий; каждый компонент режима адресации может быть только на своем месте. Например:

movzwl  foo-0x10(,%edx,2), %eax

загружает в EAX 16-битное (слово) расширение нулями с адреса foo-0x10 + edx*2. EDX - индексный регистр с коэффициентом масштабирования 2. Базового регистра нет. foo и -0x10 являются частями смещения, обе постоянные времени компоновки. foo - это адрес символа, который компоновщик заполнит и вычтет из него 0x10 (из-за -0x10 смещения времени сборки).

Если у вас есть выбор, используйте только основание вместо индекса со шкалой 1. Индекс требует для кодирования байта SIB, что увеличивает длину инструкции. Вот почему компиляторы для доступа к стековой памяти выбирают такие режимы адресации, как 8(%ebp), а не 8(,%ebp).

См. Также Ссылка на содержимое ячейки памяти. (Режимы адресации x86), чтобы узнать больше о том, когда можно использовать базу, и / или индекс, и / или смещение.


16-битное смещение кодируется только в 16-битном режиме адресации, в котором используется другой формат, который не может включать масштабный коэффициент и имеет очень ограниченный выбор регистров, которые могут быть базовыми или индексными.

Таким образом, режим, подобный 1234(%edx), должен был бы кодировать 1234 как 32-битный disp32 в 32-битном машинном коде.

Для байтовых смещений от -128 до +127 можно использовать 8-битную кодировку в сокращенной форме. Ваш ассемблер позаботится об этом за вас, используя самую короткую допустимую кодировку для смещения.


Все это идентично в 64-битном режиме для 64-битных режимов адресации, при этом disp32 также расширяется по знаку до 64-битного, как и disp8.

person Michael    schedule 14.01.2015
comment
Я все еще не совсем уверен, что такое регистр общего назначения, все ли следующие регистры считаются регистрами общего назначения: EAX, EBX, ECX, EDX, ESI, EDI, EBP и ESP? - person ; 14.01.2015
comment
Да (за исключением того, что ESP исключен из части индекса). См. Рисунок 3-11 (Вычисление смещения (или эффективного адреса)) в руководстве. - person Michael; 14.01.2015
comment
Отметим еще одно незначительное различие между base и index: когда EBP или ESP используются в качестве базового регистра, сегментом по умолчанию является SS, в противном случае - DS. MOV EAX, [EDI + EBP] загружает EAX из сегмента данных, но MOV EAX, [EBP + EDI] из сегмента стека. Тем не менее, в плоской модели Window это не имеет значения, поскольку и DS, и SS содержат один и тот же дескриптор сегмента. - person vitsoft; 14.01.2015
comment
В длинном режиме какие есть отличия? - person Paul Stelian; 24.01.2018
comment
@PaulStelian: см. Ссылка на содержимое место в памяти. (Режимы адресации x86) о том, как работают режимы адресации, включая 64-битный режим. - person Peter Cordes; 24.03.2018