73

I see this instruction in the beginning of several Windows programs. It's copying a register to itself, so basically, this acts as a nop. What's the purpose of this instruction?

2
  • 4
    The Essence: It is a two-byte NOP. So you can patch two bytes atomically without having the processor load an incomplete/incorrect instruction when he tries to execute this part of the code while you are changing it. Commented Mar 25, 2013 at 16:40
  • 13
    In x86-64 mov edi,edi is not a NOP. In x86-64 it zeroes the top 32 bits of rdi. In 32-bit code mov edi,edi can used as a NOP.
    – nrz
    Commented Apr 8, 2013 at 18:18

3 Answers 3

82

Raymond Chen (Microsoft) has a blog post discussing this in detail:

https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=9583

In short, it's a compile time addition applied in order to support run time hot patching, so the function can have the first two bytes overwritten with a JMP instruction to redirect execution to another piece of code.

4
  • 4
    You should probably add a note about the 5 empty bytes preceding the mov edi, edi instruction.
    – tmr232
    Commented Oct 3, 2015 at 9:59
  • Why not a real 2-byte NOP like 66 90? That would be more efficient: no back-end uop needed, no extra latency for EDI (in case that matters), no physical register needed to rename the output. Perhaps it's supposed to be a "signature" that tools can recognize as not naturally occurring except in hotpatch code? Commented Dec 8, 2019 at 16:52
  • 2
    @PeterCordes: Raymond Chen discusses that also devblogs.microsoft.com/oldnewthing/20130102-00/?p=5663 "the decision to use MOV EDI, EDI as the two-byte NOP instruction came after consulting with CPU manufacturers for their recommendations for the best two-byte NOP" Commented Aug 26, 2020 at 20:45
  • 2
    @BenSchwehn: Huh, probably that decision dates back to P5 Pentium days, where a 66 prefix made the instruction take an extra cycle to decode. It's unfortunate for later CPUs from P6 and onward. It's also unfortunate that it has to be a NOP, rather than optionally being a useful instruction like a 2-byte encoding of push ebp for functions that use a frame pointer. (Using the push r/m32 form with a modrm byte, not the 1-byte short form.) But that's somewhat less simple to handle, and need an alternative to not pessimize functions that don't want to push anything. Commented Aug 26, 2020 at 21:02
19

It's intended to jump to a specific location, 5 bytes before the mov instruction. From there, you have 5 bytes which are intended to be modified to a long jump to somewhere else in 32-bit memory space. Note that when hot-patching, that 5 bytes jump should be placed first, and then the mov can be replaced. Going the other way, you risk the replaced mov-jmp running first, and jumping to the 5 bytes of whatever happens to be there (it's all nops by default, but you never know).

[addition follows]

Regarding writing the 5 bytes jump - there's also the problem of there is only one instruction that will let you write more than 4 bytes atomically - cmpxchg8b, and that's not an ideal instruction for the purpose. If you write the 0xe9 first and then a dword, then you have a race condition if the 0xe9 is executed before you place the dword. Yet another reason to write the long jump first.

3
  • It's NOPs or INT3's, generally.
    – mrduclaw
    Commented Mar 30, 2013 at 2:06
  • Right, but in the case of INT3s, you definitely don't want to be running that by accident. Commented Apr 5, 2013 at 20:41
  • And in case the function is already detoured, writing the 4-byte jump target address first will atomically replace whatever rel32 the previous jmp had. (Assuming that the dword is 4-byte aligned, which it will be if functions are 8 or 16-byte aligned. It ends at the start of a function.) Commented Dec 8, 2019 at 17:07
8

courtsey Hotpatching and the Rise of Third-Party Patches presentation at BlackHat USA 2006 by Alexander Sotirov

What Is Hotpatching? Hotpatching is a method for modifying the behavior of an application by modifying its binary code at runtime. It is a common technique with many uses:

• debugging (software breakpoints)

• runtime instrumentation

• hooking Windows API functions

• modifying the execution or adding new functionality to closed-source applications

• deploying software updates without rebooting

• fixing security vulnerabilities

Hotpatches are generated by an automated tool that compares the original and patched binaries. The functions that have changed are included in a file with a .hp.dll extension. When the hotpatch DLL is loaded in a running process, the first instruction of the vulnerable function is replaced with a jump to the hotpatch.

The /hotpatch compiler option ensures that the first instruction of every function is a mov edi, edi instruction that can be safely overwritten by the hotpatch. Older versions of Windows are not compiled with this option and cannot be hotpatched.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.