2016-02-05 13 views
2

В x86 ассемблере, учитывая, что у вас естьКаково минимальное количество режимов адресации, необходимых для вычисления?

  • Немедленный режим адресации для выделяющих чисел
  • Регистрация режима адресация регистров
  • режима Прямая адресация для адресов памяти,

Зачем вам нужен Индексированный и базовый Режимы адресации указателей? Каждый может быть заменен на петлю, насколько я знаю.

Также Непрямой режим тоже не слишком полезен, так как вы можете просто использовать Direct mode вместо ссылки на адрес памяти. Какова цель первого доступа к регистру, который затем содержит указатель на адрес памяти?

Одним словом, какие режимы адресации действительно необходимы?

+3

Есть много вещей, которые можно заменить другими вещами. Зачем вам 'inc' или' sub', если у вас есть 'add'. Однако косвенный режим не просто заменяется, если вы не используете самомодифицирующийся код. Попробуйте реализовать указатели без него. – Jester

ответ

5

Хотя в теории «режим адресации» можно использовать для обращения к типу операнда, это немного запутанно, так как оно не связано с адресом. Руководство Intel использует «режим адресации», чтобы ссылаться на адресацию памяти, и я буду использовать это определение.

При сборке операнд может быть:

  • непосредственное значение
  • Регистр
  • Значение в памяти (операнд здесь адрес)

В x86 архитектура «режим адресации» относится только к последнему типу операндов: операнды памяти (адреса) и относится к методам, доступным для вычисления адресов. Режимы адресации могут быть суммированы в одном режиме настраиваемой адресации:

address = REG_base + REG_index*n + offset 

REG_base, REG_index, n и offset все настраивается, и все это может быть опущена (но вы должны по крайней мере, один, очевидно).

address = offset называется немедленной, прямой или абсолютной адресацией.
address = REG_base называется косвенной адресацией регистров.
address = REG_base + REG_index называется базовая и индексная адресация.
Аналогичным образом вы можете добавить смещение (offset) и шкалу (n).

Строго говоря, вам нужен только один режим, чтобы сделать все: зарегистрировать косвенную адресацию (address = REG). При этом, если вам нужно получить доступ к памяти, вы можете рассчитать любой адрес, который вы хотите в регистре, и использовать его для доступа. Он также может заменять операнды прямого регистра, используя вместо этого память, и непосредственные операнды путем построения значений с арифметикой. Тем не менее, для практического набора инструкций вы по-прежнему будете иметь немедленные операнды для эффективной загрузки адресов, а регистровые операнды необходимы, если вам не нужны регистры только для указателей.

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

  • Немедленное решение экономит регистр, если вы просто должны получить доступ к фиксированной переменной в памяти.
  • Base + offset действительно полезен для доступа к объектам: вы можете сохранить базовый адрес в регистре и получить доступ к отдельным членам с фиксированным смещением. Нет необходимости в промежуточных вычислениях или регистрации для хранения адреса участника.
  • Аналогично индексированная адресация используется для доступа к массивам: вы можете просто изменить регистр индекса для доступа к любому значению в массиве.
  • С помощью шкалы вы можете получить доступ к массивам с несколькими байтами (например: int) без дополнительных регистров или вычислений.
  • Комбинация всего может использоваться для доступа к элементу массива в объекте, сохраняя при этом базовый указатель для потенциального доступа к другим членам объекта.

Эти режимы адресации не требуют больших вычислений от CPU: только добавления и сдвиги. Учитывая, что x86 может умножать каждый цикл, эти операции тривиальны, но все же очень удобны.

+1

В контексте того, как обычно изучается компьютерная архитектура, непосредственные и зарегистрированные регистры рассматриваются как режимы адресации (хотя они не адресуют * память *). Кроме того, я не думаю, что реализация x86 имеет один цикл * латентность * для умножения; x86 - типичное преобразование конвейера, поэтому новое (независимое) умножение может запускаться каждый цикл, но есть разница между умножением на каждый цикл и умножением в цикле. –

+0

@ PaulA.Clayton Возможно, режимы, которые не связаны с адресами, не рассматриваются как режимы адресации. По крайней мере, я думаю, что их не должно быть. Адреса нет, и это создает недоразумения, подобные этому вопросу. И x86 делает умножение за один цикл; другие циклы считывания команд, загрузки и хранения не предназначены для умножения. Это актуально здесь, потому что у вас нет этих затрат при выполнении дополнительных вычислений в инструкции, например, при вычислении адресов. – ElderBug

+0

@ ElderBug: Большинство современных процессоров x86 могут размножаться с пропускной способностью 1 раз в сутки, но ни один из них не может делать это за один период ** латентность **. Если вход умножения является результатом предыдущего умножения, вы можете поддерживать только один на 3 такта (семейство Intel SnB). См. Http://agner.org/optimize/ для таблиц insn. Наименьшее время ожидания x86 в этих таблицах - Via Nano3000 (aka Isaiah), с задержкой 2 c для 'mul r8' или для' imul r32, r32'. Большинство процессоров x86 могут перемещаться за один цикл, но не смены и добавления. Есть очевидные преимущества кода-размера/плотности/недостатка регистров для режимов адресации, а также –

1

x86 не может делать много без регистров, поэтому я не думаю, что вы можете избавиться от режима адресации. Некоторые очень разные архитектуры могут не использовать регистры и просто иметь инструкции по памяти или стеку. IDK, как они реализуют указатели; возможно, такие архитектуры могут делать memory[memory] (запись в массиве C).

Immediate не требуется для вычислений возможно. Вы можете построить любое значение, используя несколько регистров. Начните с нуля(), inc, чтобы получить 1, с левой стороны сдвинуть его в любую нужную позицию, inc, чтобы установить низкий бит, сдвиг влево и т. Д. Так что в худшем случае нужно получить 2*popcount(N) инструкции для получения N в регистр. Обратите внимание, что немедленный подсчет сдвигов будет недоступен, поэтому очевидный метод повторного переключения на один (shl eax, да есть отдельная кодировка для переключения по одному или просто используйте add eax, eax) будет просто зависеть от положения самый старший бит набора. Итак, log2(N) + popcount(N) за очевидный сдвиг и инк.

Абсолютная (то, что вы называете прямой) адресация памяти не является наиболее полезным режимом адресации. Мы можем эмулировать его, создавая адреса с последовательностью инструкций (см. Выше) и используя [register]. Если мы пытаемся срубить, мы захотим его остановить. Как отметил Джесмер, сохраняя абсолютную адресацию, поскольку наша единственная форма была бы ужасно неудобной (или, возможно, невозможной?) Для использования.

Индекс, очевидно, доступен для исполнения, а не для необходимости: вы можете сменить и добавить с помощью отдельных инструкций.

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


Я считаю, что x86 будет по-прежнему может быть произвольно программируются с режимами простоregister и [register] адресации.

С register, [register] и immediate производительность должна быть не намного хуже, чем полная x86.


Если неявный доступ к памяти не учитывается как режим адресации, вы можете, конечно, подражать [register] с lodsd и stosd, но вы не смогли бы сделать атомарные операции чтение-модификация-запись. Это похоже на обман.

Существует также стек (push/pop): Я не знаю, является ли машина стека + регистром завершена, но она, конечно же, не программируется в обычном смысле. Конечно, если вы измените e/rsp, вы можете снова эмулировать [register], но с меньшим выбором размера операнда, чем lodsb/w/d/q/stosb/w/d/q.

x86 имеет достаточно места для хранения вещей в регистрах, если вы включаете регистры 16 ymm. Хотя я не могу придумать способ перемещения данных между целочисленными регистрами и высоким 128b ymm без использования памяти или непосредственных операндов (для vextractf128), поэтому на практике у вас больше похоже шестнадцать 16-битных регистраторов для локализации локальных иначе, чем стек. Тем не менее, это ограниченный размер, что, вероятно, означает, что 8 регистров GP в 32-битной 386 ISA по сравнению со всеми регистрами integer/mmx/ymm в 64-битной AVA2 ISA не имеют отношения к тому, является ли машина завершенной, только push/pop , регистры и никакая модификация указателя стека, кроме push/pop.