преобразовать c в сборку с предикативной инструкцией

Я хочу преобразовать этот код в сборку, используя предикативную инструкцию

If (A>B){

    C=A;
    D=B;
    E=0

}

else{

    C=B;
} 

Это правильно или как я могу использовать прыжок?

cmp R1,R2; considering B is assigned to R2 and A assigned to R1
movlf R3,R1;R3 assign to C
mov R4,R2;R4 assign to D
mov R5,0; R5 assign to E
movlt R3,R2

person amy    schedule 14.05.2016    source источник
comment
О каком языке ассемблера вы спрашиваете?   -  person interjay    schedule 14.05.2016


Ответы (1)


ВНИМАНИЕ: ответ для новичков. Может до смерти утомить опытных пользователей.


Я не уверен, что вы неправильно использовали терминологию или действительно хотите использовать предикативные инструкции1.

В последнем случае с помощью ARM v6 предикация в качестве учебного примера (и наследования ваших предпосылок об использовании регистров), сборка просто

;r1 = A    r2 = B    r3 = C    r4 = D    r5 = E
;
;A, B unsigned            | ;A, B signed
                          |
cmp r1, r2                | cmp r1, r2 
                          |
movhi r3, r1              | movgt r3, r1
movhi r4, r2              | movgt r4, r2
movhi r5, #0              | movgt r5, #0
                          |
movls r3, r2              | movle r3, r2

Здесь я привел две версии, основанные на знаках задействованных переменных.

movhi означает переместиться выше. movls означает переместить, если меньше или равно.
movgt означает переместить, если больше. movle означает переместить, если меньше или равно.
Они означают то же самое арифметическое сравнение, просто последнее использует правильные флаги для чисел со знаком.

Я сгруппировал инструкции, чтобы было легко идентифицировать блоки if-then и else.
Обратите внимание, что инструкции в одном блоке имеют одинаковый суффикс (например, hi и ls).

Что действительно делает этот код конструкцией if-then-else, а не чем-то другим, так это тот факт, что условия hi-ls и gt-le являются взаимоисключающими (только одно из двойки могут быть истинными).
Таким образом, может быть выполнен только один блок инструкций.

Использование невзаимоисключающих условий приводит к множеству операторов if-then-else.


Если вы неправильно использовали терминологию и на самом деле хотели просто реализовать условный оператор (или выбор), т. е. если-то-иначе, то обычным подходом является условная ветвь2, как уже было показано Nutan.
Вот немного более читабельная версия:

 cmp r1, r2
 bls _A_less_same_B

 mov r3, r1
 mov r4, r2
 eor r5, r5, r5

b _end_if

_A_less_same_B:
 mov r3, r2

_end_if:

На вас лежит бремя преобразования этого кода для работы с целыми числами со знаком.

Причудливые слова, оканчивающиеся двоеточием (:), называются метками. С их помощью удобно обозначать точки в коде (и данные)3.
Подумайте об этом. как гибкие номера строк.

b означает ветвь, после ее выполнения следующая инструкция извлекается из метки (адреса), указанной в качестве операнда (например, из _end_if).
bls — это просто предикат b (bls означает ветвь, если меньше или равно), обычно называемая условной ветвью.

Условные переходы ничем не отличаются от обычных переходов, но их можно «игнорировать», если указанные условия не выполняются.
Условный переход считается выполненным, если условия выполняются и ЦП выполняет команду. переход, тем самым извлекая следующие инструкции из метки, указанной в качестве операнда.
Говорят, что он не выполнен, если условия не выполняются и ЦП продолжает выполнение с инструкции после ветвь (поток программы проваливается).

Под «условиями» обычно подразумеваются установленные и снятые флаги. Некоторые инструкции, например cmp, устанавливают и сбрасывают эти флаги.
Другие инструкции, например bls, используют эти флаги.

Флаги хранятся в выделенных регистрах (ps в ARM), но есть архитектуры, в первую очередь MIPS, в которых нет регистра флагов.

Вы можете использовать свой палец для моделирования потока программы. Например, если A > B, поток выглядит следующим образом:

                            [Start Here]
                             ¯¯¯¯+¯¯¯¯¯
 cmp r1, r2                      |
 bls _A_less_same_B              + [Branch not taken, fall through]
                                 |
 mov r3, r1                      |
 mov r4, r2                      |
 eor r5, r5, r5                  |
                                 |
b _end_if                        +--[Branch always taken]----+
                                                             |
_A_less_same_B:                                              |
 mov r3, r2                                                  |
                                                             |
_end_if:                         +--[Land here]--------------+
                                 |
                                 V

Изгиб означает «перепрыгивание» кода, который мы хотим пропустить (в данном случае else).


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

Что является обязательным шагом на пути обучения.


1 Инструкции, которые извлекаются, декодируются (вероятно, также выдаются), но выполняются только в том случае, если установлены или очищены определенные флаги.

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

3 На самом деле смещения, которые станут адресами.

person Margaret Bloom    schedule 14.05.2016
comment
Это действительно отличный ответ на не очень хороший вопрос. Хорошая работа! - person David Hoelzer; 14.05.2016
comment
В ARM mov r5, #0 — лучший и более эффективный способ обнуления регистра. Странно не использовать xor, но это хорошо только на x86, где кодирование инструкций переменной длины означает, что отказ от непосредственного байта фактически экономит место и распознается как идиома обнуления. В машинном коде ARM Thumb2 eor r5,r5 — это инструкция 4B, а mov r5, #0 — инструкция 2B. Кроме того, eor будет иметь ложную зависимость от старого значения, потому что у микроархитектуры ARM нет причин использовать специальный случай eor same,same в качестве обнуляющей идиомы. - person Peter Cordes; 14.05.2016
comment
@PeterCordes Мой инстинкт подсказывал мне, что нулевой идиомы не существует, но мне было лень проверять. Спасибо за предоставление, я обновляю ответ. - person Margaret Bloom; 14.05.2016
comment
@PeterCordes: Это еще хуже: в ARM и POWER инструкции намеренно остаются зависимыми, чтобы сохранить порядок памяти (это входит в территорию memory_order_consume, вот драконы). Это архитектурно не инструкция по разрыву зависимостей. В x86 с его строгой моделью памяти зависимость не нужно отслеживать с помощью инструкций по обработке данных. - person EOF; 14.05.2016
comment
@EOF: ааа, я не знал, что отслеживание зависимостей данных было задокументировано для слабоупорядоченных архитектур (кроме Alpha). Я предполагаю, что MIPS также документирует это. Спасибо, что пролили свет на это; Я только когда-либо подробно изучал руководства Intel, которые, конечно, не упоминают об этом. Я не удивлюсь, если процессоры Intel внутренне отслеживают зависимости данных для упорядочения памяти, поэтому они могут спекулировать/ООО способами, которые не влияют на глобально видимый порядок. В любом случае, интересно, что архитектурно ARM требуется, чтобы не прерывать зависимости с помощью xor-zero. - person Peter Cordes; 14.05.2016
comment
@PeterCordes Некоторые цитаты из руководств по набору инструкций: ARM ARM ARMv7-A and ARMv7-R edition: A3.8.2 Требования к порядку доступа к памяти [...] Зависимость от адреса существует, даже если значение, прочитанное при первом доступе для чтения, не изменяет виртуальный адрес второго доступ для чтения или записи. Это может иметь место, если возвращаемое значение маскируется перед использованием[...], Power ISATM Version 2.06 Revision B: 1.7.1 Порядок доступа к хранилищу [...] Это применимо, даже если зависимость не имеет воздействие на логику программы (например, значение, возвращаемое первой загрузкой, объединяется по И с нулем[...]. - person EOF; 14.05.2016