13
69A8AB13  int         3    
69A8AB14  int         3    
69A8AB15  mov         edi,edi 
69A8AB17  push        ebp  
69A8AB18  mov         ebp,esp 

mov edi,edi doesn't make sense for me,what's it for?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
COMer
  • 1,117
  • 4
  • 14
  • 24
  • cross-site duplicate of [What is the purpose of 'mov edi, edi'?](//reverseengineering.stackexchange.com/q/250). Includes a link to Raymond Chen's blog article about it: http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx – Peter Cordes Dec 08 '19 at 17:02
  • See also [Why do Windows functions all begin with a pointless MOV EDI, EDI instruction?](https://devblogs.microsoft.com/oldnewthing/?p=9583) – Bert Huijben Sep 22 '11 at 10:15

2 Answers2

34

It's a 2 byte NOP instruction. It gets included at the beginning of any function in an image compiled with the /hotpatch option:

http://msdn.microsoft.com/en-us/library/ms173507.aspx

-scott

snoone
  • 5,409
  • 18
  • 19
  • NOP stands for "no operation", which means it does effectively nothing. – Joachim Sauer Sep 16 '10 at 15:32
  • 2
    @COMer, you would know, if you read the link that @snoone provided. – Strelok Sep 16 '10 at 15:32
  • 6
    It's a "no operation", in other words it doesn't do anything at all. It just provides some space at the beginning of the function so that the hotpatching support in the O/S has some place to put a Detours style hook. Two bytes is actually only enough space for a short relative jump, so some space is also added before the function as well (the hook will do a short jump to a location before the function that does a long jump). – snoone Sep 16 '10 at 15:34
  • 2
    It's a really inefficient choice of NOP; why would they not use `66 90` which is a true NOP? – Peter Cordes Dec 08 '19 at 16:48
  • @PeterCordes: it is specifically (apparently) a method of making sure that live-patching running executables never misfires and never live-patches a useful instruction. – torek Dec 09 '19 at 08:08
  • @torek: Yes, I understand that, and why a 2-byte NOP is necessary there. But `66 90` NOP would do the same thing. The NOP has to decode / execute every time the function is called so there is a performance downside for every function that isn't hotpatched. A true NOP would avoid a back-end uop, and avoid register-renaming using up another physical register file entry. (The extra latency for EDI's dep chain probably doesn't matter). An even better choice might some useful work like `push ebp` using the 2-byte encoding; you often want that as the first instruction anyway. Or `xor eax,eax`. – Peter Cordes Dec 09 '19 at 10:09
  • @PeterCordes: I'm pretty sure they want an instruction that *won't* occur in real code here, so that they *won't* accidentally hotpatch a useful instruction. Hence something that does useful work, or would occur in real code, is unsuitable. Of course, had they chosen the approach of *copying* the (potentially useful) instruction into the patched area, they could have avoided all of this. But that's one of those hindsight-y things. – torek Dec 09 '19 at 10:20
  • @torek: Are you saying it has to serve as a "flag" that this function is hot-patchable, and the 5 bytes before it are padding for a `jmp rel32`? You'd never find a NOP as the first instruction of a function, only after other instructions in real code as padding for alignment of branch targets (e.g. top of a loop). The hotpatched implementation of the function can implement it totally differently, compiled separately from modified source. Executions that reach it don't (AFAIK) run any of the original function's instructions so it doesn't matter whether it does useful work or not. – Peter Cordes Dec 09 '19 at 10:31
  • (You could still have the option of doing useful work for non-hotpatched executions by have multiple options that can be recognized, like the 2-byte encoding of `push ebp`, or 66 90 NOP. That might rule out `xor eax,eax` or other xor-zeroing, though, unless you only use the [`xor r/m32, reg` opcode](https://www.felixcloutier.com/x86/xor) for that and the other `xor reg, r/m32` opcode for "normal" uses in non-hotpatchable functions. x86 reg,reg instructions can be encoded in either of two ways, and assemblers / compilers normally always use the same one; only using the other for memory-src) – Peter Cordes Dec 09 '19 at 10:36
  • That's my guess. The only way to be sure would be to get information from the people who designed it, of course. What were their design considerations? – torek Dec 09 '19 at 11:10
5

According to this page: StackExchange's Reverse Engineering

In x86-64 mov edi,edi is not a NOP. In x86-64 it zeroes the top 32 bits of rdi.

I though it was important enough to point it out, in supplement to snoone's answer.

Jeach
  • 8,656
  • 7
  • 45
  • 58