5

After I compiling the codes below, the function doesn't seem to work as expected.

int cread(int *xp){

     return (xp?*xp:0);

}

I extract the counterpart in the assembly version as below.

xp in register %edx

movl $0, %eax
testl  %edx, %edx
cmovne (%edx), %eax

Could anyone tell me why the pointer xp still got de-referenced by the cmovne even when the test fails? isn't the ZF set to 1 by testl instruction when %edx is 0?

TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
JDein
  • 295
  • 2
  • 9

1 Answers1

3

The Intel instruction-set manuals seem to indicate that the CMOV operand isn't read if the condition isn't satisfied. (I suspect the "algorithm" for the instruction given in the manual, isn't quite right.)

Apparently, other people disagree; see explicit caveat here:

If the source operand is a memory operand, then it is always read, regardless of whether or not the condition is met. This means that whatever exception would have been generated from the memory read, will get generated. If the memory read would have caused a #GP or #PG, then so be it.

I suspect the reasoning is this: the instruction decoder reads instructions, computes effective addresses, and issues memory reads as early as possible, well before the instruction is fully decoded and ready for execution. So, the read to memory gets scheduled/executed early and causes a trap. It isn't until the CMOV is actually reached by the execution unit that it knows the memory read isn't needed, and starting it that late would make the instruction really slow, as well as complicate the instruction pre-fetch logic.

I only use it in its register-register form, which can't trap.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • If this is really true, then is it not an error on the part of the compiler to emit it in the OP's context? – 500 - Internal Server Error Jun 26 '13 at 05:31
  • @500-InternalServerError: yes, it would seem that would be a compiler error. They aren't always perfect :-{ – Ira Baxter Jun 26 '13 at 05:34
  • Actually i have another question, how does the compiler decides whether the operand of an instruction is signed or unsigned and then set the conditional code registers accordingly. – JDein Jun 28 '13 at 07:45
  • For example, for the below C expression, "int x =-1; unsigned y = 1; if(x>y) x+=y;" while get compiled, the assembly version can be something like mov $-1 %eax, mov $1 %edx, mov %eax %edp, add %edx %edp, cmp %eax %edx, cmovg %edp %eax (supposed x in %eax, y in %edx). As cmovg is executed based on the evaluation of ~(SF^OF)&~ZF, will the CF also be set when CPU execute the instruction cmp %eax %edx? Notice that the binary form negative number -1 is the same as 2<<32-1. – JDein Jun 28 '13 at 07:46
  • StackOverflow policy says you shouldn't ask that question in this thread. Start another StackOverflow question. It'll make it easier for you to show your example, too, which is pretty unreadable as a comment. – Ira Baxter Jun 28 '13 at 09:33
  • Ok, i will raise another question in StackOverflow. – JDein Jul 02 '13 at 09:48
  • This bounty is the prize for the [winner](http://stackoverflow.com/a/30761911/1847592) ;-) I don't see another way to award the prize for closed question. – Egor Skriptunoff Jun 11 '15 at 07:25