Проверка ввода и сборка циклов while

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

do{
   //do something
}while (x<1000 || x>9999);


person jsnjdhs    schedule 17.11.2020    source источник
comment
Взгляните на вывод компилятора в качестве примера того, как реализовать нижнюю часть этого цикла с помощью трюка сравнения без знака для проверки диапазона (addiu $t0, x, -1000 / sltiu $t0, $t0, 8999 / bne): godbolt.org.   -  person Peter Cordes    schedule 17.11.2020
comment
godbolt.org/z/adMPx7   -  person Joseph Sible-Reinstate Monica    schedule 17.11.2020


Ответы (1)


На языке ассемблера мы используем стиль if-goto-label для управляющих структур (if-then, if-then-else, for, while, do-while и т. д.). Эта форма довольно проста и естественна в ассемблере/машинном коде — она называется условной ветвью, и все процессоры имеют для нее какую-то форму. Конструкция C

if ( condition ) goto label;

соответствует условному переходу на ассемблере. И C также имеет простое goto label; без окружающего if, что называется безусловным ветвлением на языке ассемблера, и все процессоры также имеют ту или иную форму этого.


Для цикла do-while в C

...
do {
    .. do something ..
} while ( condition );
...

Шаблон if-goto-label:

    ...
Loop1:
    .. do something ..
    if ( condition ) goto Loop1;
    ...

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

Учитывая condition1 || condition2 для условия do-while:

    ...
Loop1:
    .. do something ..
    if ( condition1 ) goto Loop1;
    if ( condition2 ) goto Loop1;
    ...

В приведенном выше примере || обрабатывается путем проверки одного условия, а затем другого. Если первое условие истинно, выполняется цикл без проверки второго условия. Если первое условие ложно, оно переходит к проверке второго условия, которое затем определяет, зацикливаться или переходить к следующему оператору после цикла.

Это довольно легко переводится на язык ассемблера. Все процессоры предоставляют какой-то условный переход, может быть, в виде одной инструкции, может быть, в виде пары из двух инструкций, как в последовательности сравнения и перехода. Условные переходы используются более или менее напрямую для реализации любого оператора if-condition-goto.

person Erik Eidt    schedule 17.11.2020
comment
В этом случае условие можно оптимизировать до одной проверки диапазона. Например, двойная проверка условий в сборке (пример x86, но везде работает одна и та же логика) - person Peter Cordes; 17.11.2020
comment
И давайте также заметим, что мы также можем заменить | на ||, что часто также является хорошей оптимизацией. - person Erik Eidt; 17.11.2020
comment
Да, особенно в MIPS, где вам часто приходится материализовать условия в виде логических переменных в регистрах. Или на 32-битном ARM, где cmp/predicated-cmp часто может связывать 2 условия с нулевыми накладными расходами. - person Peter Cordes; 17.11.2020