It has been suggested to me to use TEST over CMP especially when comparing against a literal value.
for example:
invoke GetCL, 1, addr plugin_name
cmp eax, 1
jne fast_server_no_plugin_name
invoke StdOut, addr plugin_name
The code above work if I have a value specified on the command line and I use "cmp"
Change "cmp" to "test" and it doesnt work.
What am I missing ?
Rgs, striker
cmp is a subtract only updating the flags, while test is an and with only flags being updated.
You cannot use them interchangeably.
cmp eax, 1 -> test eax, eax
You cannot however test for any literal, "test eax, 5" will return non-zero for any number with bits 0 or 2 set (1, 4, 5, 9, 12, 13 etc.).
Mirno
For a zero/non-zero return value test eax,eax would work OK. But for other return values, that are not bit encoded, you can't reasonably test with a bit-wise AND, whether the result is stored or not. And in using test with a constant operand you would loose the size advantage of test eax,eax, and possibly other advantages, as this:
test eax,1
jz fast_server_no_plugin_name
cmp eax,1
jne fast_server_no_plugin_name
Assembles to this:
00401000 A901000000 test eax,1
00401005 7405 jz loc_0040100C
00401007 83F801 cmp eax,1
0040100A 7500 jnz loc_0040100C
Thanks all,
Im a lot clearer on the use of TEST now !
Good explainations too
Rgs striker
How about doing sub eax,1 and testing for 0? I'm not at a computer I check that at right now.
Hi,
TEST is a good way of checking whether a bit is set or not. It is much better than using BT or similiar. I have seen programs that use AND to test for bits. ut then they have to preserve and then restore the registers. Instead you can use TEST. TEST eax,eax is only valid to chekc whether eax is 0 or not.
Thomas
Quote from: thomasantony on June 02, 2005, 07:03:13 AM
Hi,
TEST is a good way of checking whether a bit is set or not. It is much better than using BT or similiar.
Why do you think that TEST is better than BT?
As I see it, in case I have a bit mask, use TEST, and in case I have a bit number, use BT.
Additionally, BTR, BTS and BTC instructions are very useful for working with single bits.
Hi,
TEST takes only 1-2 clocks while BT and similiar takes 3-8 clocks :bdg
Thomas :U
Quote
TEST takes only 1-2 clocks
Where did this come from, my Intel reference on PIV and similar say 0.5 clocks. Apparently pairs nicely with the other "preferred" instructions.
Quote from: thomasantony on June 03, 2005, 07:21:29 AM
Hi,
TEST takes only 1-2 clocks while BT and similiar takes 3-8 clocks :bdg
Thomas :U
Hi Thomas,
you're right (according to Agner's manual), but those instructions have different behaviour: TEST is used with bit mask, BT/BTx with bit number. Say, for instance, that EAX holds a bit number and we need to test whether is that bit set in EBX. You have to ways:
BT EBX,EAX ; in the worstest case 6 uops (latency 4 uops + additinal latency 2 uops)
JC is_set
or
MOV ECX,EAX
MOV EAX,1 ; set mask for bit 0
SHL EAX,CL ; set mask according to the bit number
TEST EBX,EAX
JNZ is_set
I've found the latter one definitely slower (there are many dependencies between the instructions).
BT with memory destination operand is very slow, probably slower than the variant with TEST.
For a zero test on a register I generally interchange TEST and OR, but these days I tend to use TEST exclusively. As has been said here many times CMP and TEST are not interchangeable, though TEST is excellent for a quick bit test as long as the result will always resolve to zero or 1. For example to check if the low order word has a non-zero value...
TEST EAX, 0FFh
jz > ; zero value in low order WORD.