Reputation: 61
if( !A && !B )
seems like it should compile to
mov eax, dword ptr[esp + A_offset]
test eax, dword ptr[esp + B_offset]
jne ~~~~~~~~~~
The compiler actually generates
mov eax, dword ptr[esp + A_offset]
test eax, eax
jne ~~~~~~~~~~
mov eax, dword ptr[esp + B_offset]
test eax, eax
jne ~~~~~~~~~~
See dump here
8B 45 F8 mov eax,dword ptr [b]
83 7D FC 00 cmp dword ptr [a],0
75 04 jne main+32h (0A71072h)
85 C0 test eax,eax
75 00 jne main+32h (0A71072h)
Why doesn't it use a single TEST instruction to save branches and instructions?
Upvotes: 4
Views: 172
Reputation: 14809
Because of the short-circuit evaluation.
if(!A && !B)
Let's pay attention to code above.
If A is truthy(not 0), !A && !B
becomes 0(FALSE)
.
Right, you don't have to check the value of the B.
It should skip(jump) the code-block for the if statement.
mov eax, dword ptr[esp + A_offset]
test eax, eax ; If `A & A`
jne ~~~~~~~~~~ ; is not 0(If A is not 0), skip this if-codeblock.
mov eax, dword ptr[esp + B_offset] ; Otherwise,
test eax, eax ; If `B & B`
jne ~~~~~~~~~~ ; is not 0(If B is not 0), skip this if-codeblock.
...... ; Both A and B are 0, and `!A && !B` is `1(TRUE)`! Run the if-codeblock.
Plus:
It seems your code is wrong..?
mov eax, dword ptr[esp + A_offset]
mov ebx, dword ptr[esp + B_offset]
test eax, ebx ; `A & B`
jne ~~~~~~~~~~ ; If `A & B != 0`, skip this code-block for the if statement.
...... ; In other words, this code-block will be run when `A & B == 0`,
; which will be `TRUE` when A is 1(0b00000001) and B is 2(0b00000010).
Upvotes: 2
Reputation: 6095
No. The test
instruction performs bitwise AND of the operands and set flags according to the result, see https://en.wikipedia.org/wiki/TEST_(x86_instruction).
So the code generated by compiler is correct.
Upvotes: 2