Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between "or eax,eax" and "test eax,eax" [duplicate]

What's the difference between or eax,eax and test eax,eax? I've seen different compilers produce both for the same comparison and as far as documentation goes they do exactly the same thing, so I'm wondering why they don't all use test eax,eax. Thinking about it and eax,eax would set the flags in an identical fashion as either but I haven't seen it in either freepascal, delphi, or msVC++.

I did compile some asm blocks in delphi and checked out the assembler source and all 3 forms are the exact same length in opcodes and also checked the intel performance PDF and it says they have the same latency and throughput.

Edit:
The question is specifically about the difference between the specific cases test eax,eax, or eax,eax and and eax,eax. All 3 give completely identical results for registers, flags, opcode length, latency, throughput. And yet for testing if 0, if not zero, or if signed, some compilers will use test eax,eax while some use or eax,eax, and I was wondering why they aren't all using test eax,eax since it makes the code very slightly clearer.

Edit2:
For reference I'm at home and only have and older msvc++ and Delphi here, but testing a variable if zero, msvc++ does test eax,eax, while Delphi does or eax,eax.

like image 657
Marladu Avatar asked May 16 '14 03:05

Marladu


People also ask

What does test EAX EAX mean?

eax contains the return value of strcmp. test is like bitwise and except it only sets the flags. Anding a value with itself gives the same value, so test eax, eax sets the flags based on whatever eax contains. ZF is set when the result of an operation is zero.

What does test function do in assembly?

The TEST instruction performs an implied AND operation between corresponding bits in the two operands and sets the flags without modifying either operand. reg, mem, and immed can be 8, 16, or 32 bits. The CMP instruction sets the flags as if it had performed subtraction on the operand.

What is the difference between the EAX and Rax registers?

rax is the 64-bit, "long" size register. It was added in 2003 during the transition to 64-bit processors. eax is the 32-bit, "int" size register. It was added in 1985 during the transition to 32-bit processors with the 80386 CPU.

What is EAX and EBX in assembly?

eax, ebx, ecx and so on are actually registers, which can be seen as "hardware" variables, meaning different than higher level-language's variables. Registers can be used in your software directly with instructions such as mov , add or cmp . The leading e means extended that is your register is 32 bits wide.


3 Answers

In general, the only difference between test and and is that test <reg>, <reg> doesn't modify its operands. Essentially test applies an and operation, discarding the non-flags part of the result. If the operands are identical, the results will be the same (as will or).

test can be a superior instruction choice because of things like micro-op fusion. As a result, test is usually preferred unless the computation would have to be repeated. The same thing goes for cmp/sub.

Search Intel's doc for "fusion" and you should find the details.

like image 83
gsg Avatar answered Oct 27 '22 02:10

gsg


The circuitry to determine that the contents of eax after test eax, eax are the same as before the instruction is simpler than the circuitry required to arrive to that conclusion for or eax, eax. For this reason, test is better.

Some compilers may have generated or at a time when it did not make any difference (before out-of-order execution), but it will make a difference with some out-of-order processors nowadays (whereas yet other OOO processors will be so sophisticated that they will recognize or eax, eax as truly equivalent to test eax, eax).

I couldn't find a reference justifying that some modern processors are actually able to infer that or reg, reg does not modify reg, but here is an answer claiming it is the case for xchg reg, reg.

like image 43
Pascal Cuoq Avatar answered Oct 27 '22 01:10

Pascal Cuoq


Just to reiterate a little of, and add a little to, what @gsg indicated, the TEST instruction does a bitwise logical comparison (essentially ANDing them bitwise internally but not storing the result) of two operands and sets the processor flags according to the result of that operation. The OR instruction does a logical OR of the source with the destination, storing the result in the destination and sets the processor flags according to the result. They both affect the processor flags the same way. So when the operands are identical, the behavior is the same. There is no difference in flags. However, when the operands are different, their behavior is then quite different. You can also test for zero with and eax,eax which also affects the flags identically.

like image 30
lurker Avatar answered Oct 27 '22 00:10

lurker