4

How could you use the TEST instruction (or a sequence of TEST instructions) to see if bits zero and four in the AL register are both set to one? How would the TEST instruction be used to see if either bit is set? How could the TEST instruction be used to see if neither bit is set? I use the emu8086 assembler.

jax
  • 53
  • 5

2 Answers2

8

(See my answer to a similar question.)

Using TEST, you can mask against 17 (= 0b10001, i.e. bits zero and four are set).

TEST AL, 17

Then:

  • ZF will be 0 if at least one bit (either bit zero or bit four) was set
  • PF will be 1 if either two or zero bits are set

So after TEST:

  • not ZF and PF - both bits set
  • not ZF but not PF - one bit set
  • ZF - neither bit set

Here is a full example:

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

Please note that this only happens to work in the case of checking for 2 bits, and specifically in the least significant byte of the masked result.

Testing for 3 or more bits would best be done with x & mask == mask using AND and CMP. (That would be efficient for the 2-bit case as well, letting you use only one branch after a couple other instructions, instead of maybe 2 branches after one TEST).

Aurel Bílý
  • 7,068
  • 1
  • 21
  • 34
  • 2
    Sorry, isn't the `ZF` actually inverted in all the cases after the text *So after `TEST`:* ??? That is, **not** `ZF` and `PF` -> both bits set; **not** `ZF` and not `PF` -> one bit set; **`ZF`** (and `PF`) -> neither bit set. I am just trying to understand. Thank you. – JFMR Jan 25 '20 at 19:35
  • 3
    @眠りネロク Yes, you're right! Corrected, sorry for the confusion :) – Aurel Bílý Jan 25 '20 at 20:19
  • @AurelBílý Thanks for confirming. – JFMR Jan 25 '20 at 20:43
  • 1
    @Jαcκsσи: I added an example to this answer. – ecm Jan 25 '20 at 22:59
  • @ecm You're a lifesaver. Thank you. – jax Jan 26 '20 at 16:34
2

How could you use the TEST instruction (or a sequence of TEST instructions) to see if bits zero and four in the AL register are both set to one?

You can use the Parity Flag trick as in the answer by Aurel Bílý -- though as noted that only works if both bits are in the low 8 bits.

Here's a simple way with multiple test instructions:

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

Equivalently, the last conditional branch may be inverted:

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

Here's another way that does not use test but instead uses a temporary register, and does an and then a cmp on that:

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

How would the TEST instruction be used to see if either bit is set?

Just provide the mask with both bits set to the test instruction, Zero Flag clear (Non-Zero) means at least one of the bits is set.

How could the TEST instruction be used to see if neither bit is set?

Again use the mask of both bits, Zero Flag set means neither bit is set.

ecm
  • 2,583
  • 4
  • 21
  • 29
  • 1
    Yup, `x & mask == mask` is the normal way to test for all bits being set. It's usually more efficient than 2 branches even if you need to save a copy of `x` for later use. – Peter Cordes Jan 25 '20 at 21:23