News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Test eax,eax

Started by Farabi, August 05, 2008, 09:25:46 AM

Previous topic - Next topic

jj2007

Quote from: PBrennick on August 07, 2008, 03:11:21 PM
JJ,
Your mention of whether it hardly matters about a few cycles is the doom of all optiimizers who do not consider how many occurences there may be of such an instruction. Also, having taught programming, I insist to say that it is just plain, poor programming practice.

The developers of MASM decided to use or eax, eax instead test eax, eax for the .if eax==0 high level construct. Either they were plain, poor programmers, or they looked at their timings and decided it didn't really matter, or they wanted to test if they could destroy the CPU (attention: irony!!).

Quote from: PBrennick on August 07, 2008, 04:01:22 PM
Mark,
I agree with the triviallity of it all and tried to reach him about it; but, I think he loves these little discussions. I even posted from the INTEL specifications but it was to no avail.

Thanks for posting the Intel specifications. You should read them carefully: They say that both or eax, eax and test eax, eax use 2 bytes of code and need one cycle on a 486.

I am just flabbergasted how such a simple question - can I use .if eax==0, or do I have to study the jxx stuff? - can turn into an ideological debate.

Mark_Larson

Quote from: jj2007 on August 07, 2008, 05:30:11 PM
Quote from: PBrennick on August 07, 2008, 03:11:21 PM
JJ,
Your mention of whether it hardly matters about a few cycles is the doom of all optiimizers who do not consider how many occurences there may be of such an instruction. Also, having taught programming, I insist to say that it is just plain, poor programming practice.

The developers of MASM decided to use or eax, eax instead test eax, eax for the .if eax==0 high level construct. Either they were plain, poor programmers, or they looked at their timings and decided it didn't really matter, or they wanted to test if they could destroy the CPU (attention: irony!!).

Quote from: PBrennick on August 07, 2008, 04:01:22 PM
Mark,
I agree with the triviallity of it all and tried to reach him about it; but, I think he loves these little discussions. I even posted from the INTEL specifications but it was to no avail.

Thanks for posting the Intel specifications. You should read them carefully: They say that both or eax, eax and test eax, eax use 2 bytes of code and need one cycle on a 486.

I am just flabbergasted how such a simple question - can I use .if eax==0, or do I have to study the jxx stuff? - can turn into an ideological debate.

there are other bugs in MASM.  Don't freak out.  A while back Hutch-- was trying different ALIGN values and one of the ALIGNS actually modified the EFLAGS!

I recommend using Jxx
BIOS programmers do it fastest, hehe.  ;)

My Optimization webpage
htttp://www.website.masmforum.com/mark/index.htm

jj2007

Quote from: Mark_Larson on August 07, 2008, 05:35:34 PM
there are other bugs in MASM.  Don't freak out.  A while back Hutch-- was trying different ALIGN values and one of the ALIGNS actually modified the EFLAGS!

Bugs are little beasts that make code fail. Translating
.if eax==0
to
or eax, eax
je somewhere

does not make code fail, as the result is identical with the test eax, eax variant. By the way, JWasm translates
.if eax
to
and eax, eax
je short somewhere

The same code under Masm translates to
or eax, eax
je short somewhere

Both variants are obviously "destructive" and therefore a case for the CPU police. Programmers to jail, hooray!

PBrennick

This is getting ridiculous, I'm outta here, this topic, I mean. JJ, do as you please. If you do not intend to listen, you should not ask. The bottleneck for the or instruction is in terms of memory --> register or register --> memory. Yes I did look and that is what I saw. That is why I said in an earlier post that if it is not a good idea at least on one occasion, then it should be avoided as it can become a habit and WILL be used when it DOES matter. I did not say it exactly like that but that is what I meant.

You know, JJ, there are times, when giving advice on this board, I say the wrong thing and when it is rightly pointed out to me, I have the good grace to accept it, wipe the egg off my face and move on. I do not like it and may even grumble; but, I accept the fact that I am wrong. You need to print out these words and post them on your wall. No one is perfect, but hopefully most of us know better than to beat a dead dog.

-- Paul
The GeneSys Project is available from:
The Repository or My crappy website

MichaelW

On my P3, in a contrived test that does not use the result, OR is faster, but in a more realistic test that does use the result there is no measurable difference.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
    .686
    include \masm32\macros\timers.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke Sleep, 4000

    REPEAT 10

      counter_begin 1000,HIGH_PRIORITY_CLASS
        REPEAT 10
          test eax, eax
          test ebx, ebx
          test ecx, ecx
          test edx, edx
        ENDM
      counter_end
      print ustr$(eax)," cycles, test",13,10

      counter_begin 1000, HIGH_PRIORITY_CLASS
        REPEAT 10
          or eax, eax
          or ebx, ebx
          or ecx, ecx
          or edx, edx
        ENDM
      counter_end
      print ustr$(eax)," cycles, or",13,10

    ENDM

    print chr$(13,10)

    REPEAT 10

      counter_begin 1000,HIGH_PRIORITY_CLASS
        xor eax, eax
        mov ebx, 1
        REPEAT 10
          test eax, eax
          jnz @F
          test ebx, ebx
          jnz @F
        @@:
        ENDM
      counter_end
      print ustr$(eax)," cycles, test",13,10

      counter_begin 1000,HIGH_PRIORITY_CLASS
        xor eax, eax
        mov ebx, 1
        REPEAT 10
          or eax, eax
          jnz @F
          or ebx, ebx
          jnz @F
        @@:
        ENDM
      counter_end
      print ustr$(eax)," cycles, or",13,10

   ENDM

    print chr$(13,10)
   
    inkey "Press any key to exit..."
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
22 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or
22 cycles, test
15 cycles, or

21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or
21 cycles, test
21 cycles, or

eschew obfuscation

jj2007

Quote from: MichaelW on August 07, 2008, 08:18:15 PM
there is no measurable difference.
Thanxalot, Michael. This is one half of the story: The Masm developers didn't care because they knew there was no difference.

Quote from: jj2007 on August 07, 2008, 06:40:41 PM
Bugs are little beasts that make code fail. Translating
.if eax==0
to
or eax, eax
jne somewhere

does not make code fail
This is the other half of the story: I posted this some hours ago, and over 20 people including some bots have seen it. Nobody noticed my (unvoluntary) error. If we push newbies, with folkloristic stories about CPU's that "must" be slower for instructions that do "real" hard destructive work, towards using jxx instead of the high level constructs, then we reinstall the reputation of assembler being a secret code for grim-looking men carrying punchcards with them.

PBrennick

Michael,
None of those tests involve a memory to registe,r or register to memory operation which is where the bottleneck is as I already said.

Also, Michael, something for you to think about in terms of your macros is the fact that they do not perform any cache loading so a test between instructions where one writes to the cache and another doesn't is not really valid.

And finally, back to the original point of all this OR 'is' destructive.

-- Paul
The GeneSys Project is available from:
The Repository or My crappy website

bozo

when i used TASM where no invoke was available.
if a register returned either TRUE or FALSE for success, i'd use:
   
    dec eax
    js @fail


or if it was -1, like after calling CreateFile
   
    inc eax
    jz @fail



    xchg eax,ecx
    jecxz @fail


Michael, would first 2 examples be faster than OR/TEST? ..probably not.

raymond

QuoteI also CHEAT and use MMX registers to temporarily save register values.

Correct me if I'm wrong but the MMX registers are the same ones used by the FPU. For those who may not be aware of it already, numerous WinXP functions (notably MessageBox and similar) may trash the FPU/MMX registers (this was not happening with Win98).

So, using those registers to store data may be safe as long as those trashing APIs are not used. However, there is no information as to which ones are at fault. Beware at least of those which may need to perform some calculations (even if only 2+2) such as window sizing of any kind.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

hutch--

 :boohoo:

I am still fascinated at the level of waffle surrounding this "debate". The difference between high and low level code is well understood, the relevance of techniques depend on WHERE it is being applied and the criterion of what matters and what does not resides in the eye of the beholder.

RE bashing low level code to death, we have a Laborotory just for doing that as enough assembler programmers are interested in chasing speed where it matters and the deciding factors of how and where the designs are applied are also in the eye of the beholder. Prescribing "preferred" code design based on personal arbitrary criteria is a waste of space, argue about why blondes are more fun than brunettes, whether you are a Republicrat or a Democan, whether you drink tea of coffee for breakfast but spare us stuff that is objectively tested in the LAB and subjectively applied by the beholder.

Spare a thought for the chip designers at Intel and why they bothered to distinguish between an AND and a TEST, what the logical difference is between a weak inclusive "OR", and exclusive or "XOR" and the logic of "NOT", "NEG" and various others. I doubt at the time of the design of the original x86 that it was done to waste chip space, they all have their place, just use what works to do the job.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: raymond on August 08, 2008, 12:56:10 AM
QuoteI also CHEAT and use MMX registers to temporarily save register values.

Correct me if I'm wrong but the MMX registers are the same ones used by the FPU. For those who may not be aware of it already, numerous WinXP functions (notably MessageBox and similar) may trash the FPU/MMX registers (this was not happening with Win98).

So, using those registers to store data may be safe as long as those trashing APIs are not used. However, there is no information as to which ones are at fault. Beware at least of those which may need to perform some calculations (even if only 2+2) such as window sizing of any kind.


Raymond, this is really interesting. Do you have any reference saying which API's misbehave? I just tried with an ordinary MessageBox, but MMX registers did not change.

(at bottom of ShowQwMMX proc posted above)

int 3
invoke MessageBox, 0, chr$("MMX registers trashed?"), chr$("Test:"), MB_OK
  emms ; be nice to others: cleanup
  ret
ShowQwMMX endp

Mark_Larson

Quote from: raymond on August 08, 2008, 12:56:10 AM
QuoteI also CHEAT and use MMX registers to temporarily save register values.

Correct me if I'm wrong but the MMX registers are the same ones used by the FPU. For those who may not be aware of it already, numerous WinXP functions (notably MessageBox and similar) may trash the FPU/MMX registers (this was not happening with Win98).

So, using those registers to store data may be safe as long as those trashing APIs are not used. However, there is no information as to which ones are at fault. Beware at least of those which may need to perform some calculations (even if only 2+2) such as window sizing of any kind.

VC++ starts using mm0 and moves UPWARDS mm1, then mm2, etc.  I start at the back (mm7) and move DOWNWARDS, so it makes it safer :)  Since the FP and MMX registters are the same the same thing applies for how VC++ uses the FP registers.
BIOS programmers do it fastest, hehe.  ;)

My Optimization webpage
htttp://www.website.masmforum.com/mark/index.htm

PBrennick

As JJ is hinting at, it would sure be useful to have such a list, unfortunately I doubt we will find one and looking at it API by API would be a nightmare. It is useful to know that the MessageBox is safe (thank you JJ). If anyone finds any that should be on a warn off list, perhaps generating a list of these APIs in either or both of our SDKs would be very helpful to programmers.

-- Paul
The GeneSys Project is available from:
The Repository or My crappy website

jj2007

Quote from: PBrennick on August 08, 2008, 01:56:16 PMIt is useful to know that the MessageBox is safe
Paul, I made some quick tests, and observed no changes of MMX registers when emms was used on exit of my proc; however, I saw occasional changes when emms was not used. It is not easy to reproduce, though. May Raymond has hands-on experience with the MessageBox...?
Googling for various mmx trash overwrite etc variants yields nothing; which leads to the suspicion that either very few people use mmx in their codes, or the problem is limited to a handful of exotic API's. We should ask Microsoft directly  :wink

raymond

QuoteQuote from: PBrennick on Today at 09:56:16 AM
It is useful to know that the MessageBox is safe

As far as I'm concerned, MessageBox is NOT safe.

I've been caught a few times with algos returning garbage when data was left temporarily in FPU registers while caling MessageBox to alert the user. You can check that out with Ollydebug and watch what is happening with the FPU registers after calling the function.

The MS programmers found a new toy with the MMX registers (at least while developing WinXP, I have no experience with ME nor 2000) and seem to have used them whenever a calculation is required (even if it involves only integers). That's why I would put all APIs displaying a window on the watch list. If you suspect that an API requires some calculation, it should also be put on the watch list.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com