Как использовать инструкцию TEST, чтобы увидеть, установлены ли два бита? - PullRequest
4 голосов
/ 25 января 2020

Как вы могли бы использовать инструкцию TEST (или последовательность инструкций TEST), чтобы увидеть, установлены ли оба бита ноль и четыре в регистре AL на один? Как будет использоваться инструкция TEST, чтобы увидеть, установлен ли какой-либо бит? Как можно использовать инструкцию TEST, чтобы увидеть, установлен ли ни один бит? Я использую ассемблер emu8086.

Ответы [ 2 ]

8 голосов
/ 25 января 2020

(см. мой ответ на аналогичный вопрос.)

Используя TEST, вы можете маскироваться против 17 (= 0b10001, т.е. установлены биты ноль и четыре).

TEST AL, 17

Тогда:

  • ZF будет 0, если был установлен хотя бы один бит (ноль или четвертый бит)
  • PF будет 1, если установлены два или ноль битов

То есть после TEST:

  • не ZF и PF - оба бита набор
  • не ZF, но не PF - один бит установлен
  • ZF - ни один бит не установлен

Вот полный пример:

    TEST AL, 17
    JZ none_set
    JPE both_set
one_set:
    ...
none_set:
    ...
both_set:
    ...

Обратите внимание, что это работает только в случае проверки на 2 бита и, в частности, на младший байт маскированного результата.

Лучше всего проверить на 3 или более бит сделать с x & mask == mask, используя AND и CMP. (Это было бы эффективно и для 2-битного случая, позволяя вам использовать только одну ветвь после пары других инструкций вместо, возможно, 2 ветвей после одной TEST).

2 голосов
/ 26 января 2020

Как вы могли бы использовать инструкцию TEST (или последовательность инструкций TEST), чтобы увидеть, установлены ли оба бита ноль и четыре в регистре AL на один?

Вы можете использовать трюк с флагом четности, как в ответе Аурела Били - хотя, как уже отмечалось, он работает, только если оба бита находятся в младших 8 битах.

Вот простой способ с несколькими инструкциями теста:

    test al, 16
    jz not_both_set
    test al, 1
    jz not_both_set
both_set:
    ...
not_both_set:

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

    test al, 16
    jz not_both_set
    test al, 1
    jnz both_set
not_both_set:
    ...
both_set:

Вот еще один способ, который не использует test, а вместо этого использует временный регистр и делает and, а затем cmp на этом:

    mov ah, al
    and ah, 17
    cmp ah, 17
    jne not_both_set
both_set:
    ...
not_both_set:

Как будет использоваться инструкция TEST, чтобы увидеть, установлен ли какой-либо бит?

Просто предоставьте маску с обоими битами, установленными на test инструкция «Очистить нулевой флаг» (отличная от нуля) означает, что установлен хотя бы один из битов.

Как можно использовать инструкцию TEST, чтобы увидеть, установлен ли ни один из битов?

Снова используйте маску обоих битов, Zero Flag s et означает, что ни один бит не установлен.

...