Это описано в руководстве 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