5

Currently I am doing this to test for a negative number in x86 assembly (r/m32,imm8):

83F800 CMP EAX, 0

This can be followed by JL. This is 3 bytes and supposedly clocks at "1/2". I could use TEST EAX, or CMP EAX,imm32 (encoding 3D), both of which clock at "1", but take 5 bytes. In general, if I am trying to minimize code size, is the way I am doing it correct? Once again, this is to test if a number is less than zero.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • What microarch are the timings for? – harold Mar 16 '13 at 19:38
  • You could probably skip the `CMP` in many cases if you use `JS` ("jump if sign"). The sign flag _should_ already be set correctly by the last arithmetic or move instruction, and if the sign flag is set, the result is negative. Though there are probably weird special cases where that won't work for some obscure reason. – Damon Mar 16 '13 at 19:40
  • @Damon moves don't change the flags though – harold Mar 16 '13 at 19:41

2 Answers2

5

add eax, eax is only two bytes (01 C0 or 03 C0), but destructive. (check for carry afterwards)

test eax, eax is also only two bytes (85 C0). (check for sign afterwards)

harold
  • 61,398
  • 6
  • 86
  • 164
  • Ok, so if I use test, then JL will work? According to my book JL goes if SF<>OF, and since test clears OF then I should be ok it seems. – Tyler Durden Mar 16 '13 at 19:45
  • @TylerDurden yes but only accidentally, so to speak, because it clears OF, as you say. Might as well use `JS` and make it obvious, right? – harold Mar 16 '13 at 19:46
  • I am using a mini-assembler that does not have JS in it currently. – Tyler Durden Mar 16 '13 at 19:52
  • 1
    Ok so `JL` then, doesn't matter – harold Mar 16 '13 at 19:54
  • 5
    "test eax, eax" is my preferred answer, because it is nondestructive and it it pretty obvious it sets the CC sign bit, according the register sign bit. – Ira Baxter Mar 16 '13 at 20:35
  • `test eax,eax` sets FLAGS exactly like `cmp eax,0`: [Test whether a register is zero with CMP reg,0 vs OR reg,reg?](https://stackoverflow.com/a/33724806) – Peter Cordes Dec 13 '22 at 22:11
3

You can use:

or      eax, eax

it is one byte shorter (only two bytes op code) instruction!

GJ.
  • 10,810
  • 2
  • 45
  • 62
  • 1
    OR is [less efficient than TEST](https://stackoverflow.com/a/33724806) on modern x86 CPUs; no need to write EAX again, increasing the latency of the dependency chain for whatever reads it next. This OR idiom dates back to 8080, and has never been necessary or had any advantages on 8086 vs. TEST. (Except maybe on P6 where writing a register again could mitigate register-read stalls if it might be cold for later reads.) – Peter Cordes Dec 13 '22 at 22:10