2013-09-06 4 views
0

В большинстве инструкций наборы команд ветвления выполняются на основе флагов в регистре состояния.Зачем нужны инструкции для филиала?

На языках более высокого уровня логическое значение является типом данных, который может быть создан оценочным выражением (обычно ==,! =, <,>,> =, < = и другими вариантами) и хранится в переменной.

Почему именно сборка выбирает ветку на флажках статуса вместо инструкций, которые хранят логический результат в регистре?

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

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

+0

Как вы собираетесь «тестировать из регистров общего назначения», не имея регистра состояния для хранения результата теста для последующей инструкции перехода? –

+0

У многих ЦП есть инструкции, которые устанавливают логический флаг на основе условий в дополнение к ветвям. x86 - один из примеров. См., Например, раздел 6.6.5 на [этой странице] (http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH06/CH06-4.html). –

+0

@JoeHass Сохраните результат в другом регистре общего назначения. Имейте в виду, что я не предполагаю x86, у которого очень мало регистров, я не предполагаю какого-либо определенного набора команд или какого-либо определенного количества регистров. – Pharap

ответ

3

Если вы хотите, чтобы «сохранить логический результат в регистре», вы должны были бы отдельные инструкции для <, <=, >, >= и т.д. Вы бы также нужен один набор для знакового сравнения и другое для знака сравнения ,

В наборе команд x86, есть одна инструкция для всех из них, cmp (который устанавливает кучу флагов), а затем использовать соответствующую jxx или setxx инструкцию, чтобы посмотреть на флаги, которые вас интересуют (например, для условные переходы, вы используете jb, jbe/jna, ja, jae/jnb для знака ("ниже"/"выше"), и jl, jle/jng, jg, jge/jnl для знакового ("меньше"/"больше «)).

Другая особенность этого подхода заключается в том, что вы можете фактически проверять флаги после выполнения операции мутации, например, переносить дополнения или вычесть заимствования. Пример (предположим, что esi указывает на 128-битным номером, который добавляется к другим 128-битным количестве, edi указывает):

add [edi], [esi] 
adc [edi+4], [esi+4] 
adc [edi+8], [esi+8] 
adc [edi+12], [esi+12] 
jc overflow 

Это всего 5 команд (ну, гипотетически, в действительности, инструкции x86 не может оба операнда должны быть адресами, один должен быть регистром, а это означает, что загрузка этого регистра потребует больше инструкций). Использование «логического результата в регистре» приближается, похоже, было бы сложнее (но я думаю, что не очень, если вы используете набор команд, который позволяет трехстороннее дополнение).

+0

Да, но инструкции для разных булевых сравнений заменяли бы прыжки, так как это означало бы, что текущие инструкции перехода будут заменены одним «скачком if» и, возможно, «прыгать, если нет». Флаги фактов устанавливаются как побочный эффект операций alu, безусловно, является возможной причиной выбора метода flags. Кроме того, я не говорю о x86 специально, поэтому я включаю в себя наборы, которые позволяют добавлять 3-сторонние дополнения. – Pharap

1

Ответ Криса прямо на. Я бы добавил только, что, не желая связывать большой регистр только для того, чтобы провести результат сравнения, бит флага естественно выпадает из операций арифметического регистра, и специально назначенный регистр флагов является хорошим местом для них.

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

Бит старшего разряда регистра, если число находится в двоичном дополнении, является битом знака.

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

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

Мой любимый пример аппаратных средств базового уровня является Harry Porters's Relay Computer. Там вы можете увидеть, как регистр флагов действительно помогает минимизировать аппаратное обеспечение и упростить набор команд.

-1

Ну, во-первых, как вы думаете, разница между логическим ответом и флагом? True/false vs true/false? такой же. Языки более высокого уровня теряют целую кучу бит в переменной, так что в основном один из этих битов содержит логический результат. Реальность такова, что только очень неэффективный компилятор фактически генерирует и уничтожает все эти биты в регистрах. Довольно часто используется одна или серия сравнений и ветвей в условных выражениях, и gprs не потребляются для реализации этого языка высокого уровня. В других случаях, в зависимости от сложности логического, тогда gpr определенно используется, и операции boolean alu и другие gprs потребляются для вычисления этого логического результата, тогда есть окончательное сравнение, если нуль и ветвь, если нуль или не выполнить задачу (почему еще вы бы вычислили логическое значение, если бы вы не захотели сравнить его и сделать что-то на основе сравнения? оптимизатор удалит все из этого кода в противном случае).

Типичный подход - это четыре флага, которые тривиально выпадают из операции alu, ноль, минус, перенос (a.k.a. беззнаковое переполнение, заимствование a.k.a.) и переполнение подписей. NZCV. Затем список белья филиала по условным инструкциям. У вас есть эффективность условного вычисления на любой операции alu. Большинство операций alu действительно записывают выход регистра, даже если вы не заботились об этом выходе. Но часто команда сравнения (вычитание без сохранения результата) достаточна для большинства условностей и присутствует. Иногда, если вам повезло, вы получаете тестовую инструкцию (И без сохранения результата). В большинстве случаев вы знаете, что сравнение идет, и это только одно сравнение одной условной ветви. Иногда есть время, когда вы можете установить флаги один раз, затем сделать две или более условных ветвей в строке, не переустанавливая флаги условий, они сохраняются через поврежденную ветвь. Это исключение, а не правило. Флаги, являющиеся халявой, вероятно, являются причиной этого популярного подхода.

Весьма разумно иметь список правил сравнения, установить флаг, если a == b, установить флаг, если < b, установить флаг, если < = b и т. Д. Тогда у вас есть только ветка, если флаг установлен и имеет ветвь, если флаг очистить инструкцию на сервере. Есть один процессор, который я знаю о том, как это делается. Вы не хотели бы тратить весь gpr, чтобы сохранить этот бит, но это может быть разумно сделать по различным причинам, о котором я думаю, не делает этого.

Есть один, который я знаю о том, что psr является gpr, что означает, что он действительно не является gpr, потому что он особенный, но он используется/доступен как gpr. Таким образом, ваш выход alu сбрасывает эти флаги в gpr, нет списка условных ветвей, вместо этого я думаю, что есть два, ветвь, если бит X в регистре Y установлен или разветвлен, если бит X в регистре Y не установлен. (это может быть хуже, чем SKIP, если бит x в y задан или пропустить, если бит x в y не установлен). И вы должны объединить одну или несколько из них в строке для более сложных ветвей (ветвь, если она равна или выше, и т. д.).

Существует тот, который я знаю о том, что у него нет флагов, в нем, в принципе, есть сравнение и прыжок, если они равны и сравниваются и прыгают, если не равны. на основе регистра. Вы должны синтезировать все другие условия, подписанное или неподписанное переполнение, n бит и т. Д. Сжигание обоих gprs и циклов команд очень неэффективно. Я могу видеть красоту в ней, в то же время ненавижу боль, связанную с необходимостью записывать регистры и так много циклов.Я предполагаю, что цель заключалась в том, чтобы избежать необходимости переносить флаги состояния процессора из одной инструкции в другую и иметь дело с конвейером (компромисс был более опасным для трубопровода из-за промежуточных результатов всей математики, участвующих в синтезе флагов alu).

Практически любой процессор, который вы можете выполнять всю логическую работу, используя gprs и операции alu, приводя к регистру, который является либо нулевым, либо нет, тогда вы можете выполнить эту заключительную одну или две команды в зависимости от процессора, чтобы прыгать если этот регистр равен нулю. Вам не нужно использовать список ветвей ветки, если сравнивать, если вы этого не хотите.

Суть в том, что это огромные отходы для хранения отдельных бит результатов в gprs. Надеюсь, вы поймете, что это неэффективно, поэтому аргумент, ссылающийся на использование gprs, является ошибочным IMO. Флаги какого-то рода эффективны просто потому, что они не используют gprs. Не будь флагом (сравнивать и прыгать в одной инструкции) один флаг или несколько флагов. Делайте это самостоятельно против большого количества сравнений и нескольких ветвей против множества филиалов, а свободные сравнения - все имеют свои плюсы и минусы. Я думаю, что подход с четырьмя флагами является самым популярным, потому что флаги - халява alu, и, потому что мы привыкли так долго делать это.

+1

Хорошая вещь о x86 заключается в том, что вы можете использовать ее в обоих направлениях: вы можете использовать инструкции 'setXX' для хранения однобитовых результатов в регистре или в памяти. :-) Но сначала делаются флаги. –

Смежные вопросы