5

When I compile this piece of code

unsigned char A[] = {1, 2, 3, 4};

unsigned int
f (unsigned int x)
{
  return A[x];
}

gcc outputs

mov edi, edi
movzx  eax, BYTE PTR A[rdi]
ret

on a x86_64 machine.

The question is: why is a nop instruction (mov edi, edi) there for?

Im am using gcc-4.4.4.

1 Answers1

3

In 64-bit mode, mov edi, edi is not a no-op. What it does is set the top 32 bits of rdi to 0.

This is a special case of the general fact that all 32-bit operations clear the top 32 bits of the destination register in 64-bit mode. (This allows a more efficient CPU than leaving them unchanged and is perhaps more useful as well.)

jilles
  • 10,509
  • 2
  • 26
  • 39
  • oh.. can you cite any sources for that? – osgx Nov 16 '10 at 01:34
  • 1
    Okay. I think you're right about this. it's just a fancy way to clear the top of rdi. After rereading the question I understand the OP is not asking "Why does this hotpatchable function starts with `mov edi, edi`" but something like "Why does this x86-64 assembly code looks like an hotpatchable function." Also the code doesn't even specify the `ms_hook_prologue` attriubte, the latest release of gcc doesn't support ms_hook_prologue for x86-64 and it seems that on x86-64 it will use a `leaq [%rsp + 0], %rsp` prologue instead of `mov edi, edi` (http://tinyurl.com/39fye3w). I will delete my answer – Alex Jasmin Nov 16 '10 at 11:20
  • I see, thanks. But wouldn't it be more useful if the ABI specified 32bit arguments in registers should already have the upper bits cleared? – Luís Fernando Schultz Xavier Nov 16 '10 at 16:10