2

I have the following question: Could it be that OR EAX, EAX represents a if statement?

The reason why I ask is, I have read the following in an assembly code:

....
OR EAX, EAX
JNZ funct.A
.....

Before the line OR EAX, EAX comes, the function strcmp is called which has the return value 00000001 stored in EAX. So I have found out that: if the return value is greater than zero indicates that the first character that does not match has a greater value in string1 than in string2.

So, my first question would be: What does that mean "if the return value is greater than zero indicates that the first character that does not match has a greater value in string1 than in string2."

And the second question would be: Can I translate the assembly code in pseudo C-Code like the following:

if(EAX == 1){
   funct.A;
}

Is that ok? Or completely wrong? If yes, then what would your suggestions?

2
  • "greater than zero" is only half of the description; the other half is "smaller than zero". But in this case all that is tested for is not zero, i.e., it does not matter whether the second string is "greater" or "smaller", the code merely tests for equal strings. This is indicated by a zero in EAX, which is tested here with the OR.
    – Jongware
    Jun 22, 2014 at 11:38
  • 2
    if an answer helps you then you should mark it as accepted to tell the community that this question has been solved, that'll contribute to the reputation of both the asker and answerer
    – phuclv
    Sep 6, 2014 at 12:37

3 Answers 3

7

x86 conditional branch and move instructions decide whether to jump/move or not depending on the flags. If the appropriate flag(s) are set they'll take the action, hence any instructions that affect the flag(s) can be used, not only CMP. For example to check if the high bits in rax are zero SHR rax, 32; JZ RAX_IS_0 can be used which saves a CMP. As a result, shorter instructions are generally preferred

The most commonly used one is TEST. AND eax, eax can also be used, since it's exactly the same as TEST except it destroys the destination (but that's irrelevant in cases where source and dest are the same register like this). However sometimes OR is also used (most likely emitted by the Delphi compiler) because OR reg, reg gives the same results as AND reg, reg. If you check the disassembly you'll notice that CMP is one byte longer:

83 F8 00  cmp  eax, 0
09 C0     or   eax, eax
21 C0     and  eax, eax
85 C0     test eax, eax

After the above instructions the SF, ZF, PF, CF, OF (and AH with cmp) will be modified. JNZ will check ZF and jump if it's not set, i.e. eax is non zero

Performance-wise TEST should always be used because TEST can macro-fuse with Jcc but not AND and OR

1
  • 1
    It seems the inefficient-on-modern-CPUs or reg,reg idiom originated from 8080 which didn't have a test; it has ora a to OR the accumulator with itself. (And ana a to AND with itself, but unfortunately for macro-fusion on Sandybridge-family which can macro-fuse and but not or, people settled on ora and kept using it when moving to 8086). My answer on Test whether a register is zero with CMP reg,0 vs OR reg,reg? explains why it's inefficient and mentions history. You still see that idiom in SO Q&As; people keep learning from old bad examples Apr 22, 2021 at 8:43
3

I would translate this to the pseudo code

if (strcmp(…)) 
    goto funct.A;

The point of the OR is that strcmp(), like all C functions returning integer scalars, returns its result in EAX. In order to do conditional jump, you need to set the conditional flags based on the value, and OR EAX, EAX has the nice property that it sets the conditional flags (particularly ZF, which is tested by the subsequent jump) without modifying the value in EAX.

Not quite sure why OR would be used instead of TEST here; the function seems to be identical for the purpose of the code.

2

in x86 / x86-64 or represents a logical or.

In your example

 OR EAX, EAX

Performs the logical bitwise or operation. If EAX is zero, the result will be all zeroes, and the zero flag will be set, which most likely will is the whole point.

I might render the code you showed as

if(EAX != 0)
{
     func.A
}

It's hard to see exactly what the significance of this is without knowing the wider context of what is happening. I would guess that the actual string comparison should return a 0 into the EAX register should the strings (or parts of strings) match.

Indeed this is a normal approach: https://stackoverflow.com/questions/11663745/compare-arrays-of-characters-in-x86-assembly

This above post relates a method for comparing strings in x86. The jne and cmp instructions are used rather than the jnz, but the concept may hold water to your situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.