Страницы

Поиск по вопросам

среда, 11 декабря 2019 г.

Явные отличия CMP от TEST

#ассемблер


Я начал изучать устройство одной программы недавно, целиком написанной на ассемблере
(т.е никакие трансляторы в машинный не применялись, как в языках высокого уровня).
Так вот, в ней я очень часто встречаю конструкции вида TEST AL, AL ; TEST EAX, EAX и т.д.

Вот вопрос: почему применяется TEST, а не CMP? Да и какой смысл сравниваться с самим
собой? Насколько я знаю, TEST использует логическое "И" (AND). Проясните, пожалуйста,
в этих деталях я не особо просвещён.
    


Ответы

Ответ 1



Команды вида test reg, reg используется для сравнения значения регистра с нулем. После этой операции флаги нуля, знака и чётности либо устанавливаются, либо сбрасываются. Почему не cmp reg, 0? Потому что в скомпилированном виде test reg, reg на целый байт короче, ну и по скорости наверное разница есть. test эквивалентен побитовому and, за исключением того, что модифицируются только флаги, но не операнды. Обычно это нужно, чтобы узнать, установлены ли определенные биты в регистре. А cmp эквивалентен обыкновенному вычитанию, но аналогично модифицирует флаги, не изменяя операнды.

Ответ 2



CMP Reg1, Reg2 l =2 байта, t = 3 такта, спаривается в любом конвеере TEST Reg1, Reg2 l =2 байта, t = 3 такта, спаривается в любом конвеере CMP Reg, Const l = 3-4 байта t = 4 такта, спаривается в любом конвеере Разница в количестве используемых регистров, в результате оптимизации кода и наборе изменяющихся флагов.Т.к. обычно используется следующий формат: TEST Reg1, Reg1, ну и соответственно логике - TEST сравнение с 0 :)

Ответ 3



Установление флагов после этой короткой инструкции test ax,ax 85C0 , позволяет с легкостью не только читать код, благодаря простоте вида , но и уменьшить процессорные временные затраты (реализация AND (логическое "И") - проще сумматора, на нём резализованного, когда используется CMP (вычитание). В подавляющем большинстве случаев, после проверки на 0 используются команды условного перехода Jcc (в данном случае JE (equal) переход если равны (ZF=1)). mov ax, 0 test ax, ax ; and 0 with 0 je flag_not_set ; always taken mov ax, 1 test ax, ax ; and 1 with 1 je flag_not_set ; not taken Вот схематика на уровне микроинструкций:

Комментариев нет:

Отправить комментарий