玩WinDBG的时候, 发现函数的反汇编代码的最开始部分总是包含一条move edi, edi的指令. 比如下面的代码
static unsigned int __stdcall Fibonacci_stdcall(unsigned int n) { switch(n) { case 0: STOP_ON_DEBUGGER;return 0; case 1: return 1; default: return Fibonacci_stdcall(n-1)+Fibonacci_stdcall(n-2); } }
生成汇编代码的开头部分如下:
Push EBP和Mov EBP, ESP两条指令是标准的栈框架建立的指令, 但是Mov EDI, EDI是做什么的呢? 看起来它就是两个字节的NOP指令.
正解:
mov edi, edi的确是个双字节的no-op指令, 它存在的目的是使得hot-patching称为可能. 它使得对一个函数的hot-fix得以生效且不需要重启机器, 甚至是正在运行中的应用程序也不需要重启. 不重启是通过在运行时将这个2字节的NOP指令替换为一个short jump指令, 这个short jump会使程序跳转到另一个long jump指令处, 而这个long jump指令会使得程序的执行跳转到hotfix的函数处. 这里需要2-byte的指令, 这样, 在patch应用程序的时候指针就不会指向某个函数的中间部分了.
参考资料
==========
Why does the compiler generate a MOV EDI, EDI instruction at the beginning of functions?
http://blogs.msdn.com/b/ishai/archive/2004/06/24/165143.aspx