函数开始处的MOV EDI, EDI的作用
0:000> u TextOutA-0x0a L 10
GDI32!NtGdiTransparentBlt+0xa:
77efc43f ff12 call dword ptr [edx]
77efc441 c22c00 ret 2Ch
77efc444 90 nop
77efc445 90 nop
77efc446 90 nop
77efc447 90 nop
77efc448 90 nop
GDI32!TextOutA:
77efc449 8bff mov edi,edi
77efc44b 55 push ebp
77efc44c 8bec mov ebp,esp
很明显,两个字节的MOV EDI,EDI指令什么事情也不做,那么,就有两个问题:第一,为什么不直接从函数体开始而要从这条什么都不做的指令开始呢?第二,即使需要在函数一开始空出两个字节,为什么不直接使用两条NOP指令,而要使用这条MOV指令呢?在网上查阅一些资料后,得到了答案:
对于第一个问题,答案是为了实现hot-patching技术,即运行时修改一个函数的行为。修改过程如下:把MOV EDI, EDI修改为一条短跳转指令(一条短跳转指令恰好两个字节),把MOV EDI, EDI上面的五个NOP修改为一条长跳转指令(一条长跳转指令恰好五个字节),短跳转指令跳到长跳转指令上,长跳转指令跳到修改后的函数体上。
对于第二个问题,答案是为了提高效率。执行一条MOV指令比执行两条NOP指令花费更少的时间。
下面是在网上搜索到的相关资料:
http://blogs.msdn.com/ishai/archive/2004/06/24/165143.aspx
在这篇日志中作者指出这是一种实现hot-patching和hot-fix的技术,而且解释了为什么不使用detours技术来实现hot-patching。此外,作者提到了具体是如何使用这种技术来实现hot-patching的,但是只是一句话带过。
http://msmvps.com/blogs/kernelmustard/archive/2005/04/25/44413.aspx
这篇文章中作者从效率和其它方面详细解释了为什么选择用这种技术来实现hot-patching以及为什么要这样实现(短跳转加长跳转而不是一次性长跳转)。
http://xelf.info/knowledge/MemoryCopy.cpp
这里给出了具体的memcpy的C语言源代码。如果在安装VC6的时候选择了安装CRT源代码,则在VC安装目录的SRC/INTEL/目录中有memcmp.asm等文件,它们就是对应的CRT函数的源代码,这些源代码中也都有详细的注释。
另外,在自己的日志http://blog.csdn.net/jcwKyl/archive/2008/03/25/2217428.aspx里面,曾经对strcmp函数中的MOV EDI, EDI指令感到困惑,其实只要看看strcmp.asm中的源代码就可以明白,那条MOV EDI, EDI完全是为了内存四字节对齐的。源代码中写的是align 4,在运行时,如果需要一个填充字节,则会填充一条NOP指令,如果需要两个字节来填充,则会填充一条MOV EDI, EDI指令,之所以不用两条NOP,是出于效率的考虑。
转载于:https://www.cnblogs.com/vcerror/p/4289113.html
函数开始处的MOV EDI, EDI的作用相关推荐
- vim怎么跳转到函数定义处_Vim、gvim操作跳转光标区块和代码块的跳转
~ 回复 以下关键词 查看更多IC设计教程 ~目前支持的关键词有:Innovus ICC or IC CompilerDC or Desig ...
- vim跳转到函数定义处
跳转到函数定义处,首先需要有tag文件,生成tag文件的方式为: 在要包含所有代码的目录(其实可以直接在根目录)执行: ctags -R 然后用vim打开代码,在任意一个调用函数的行,把光标放在被调用 ...
- Atom快速跳转到函数定义处
安装插件 goto definition 快捷键 ctrl+alt+enter
- python中rename函数_python os.rename(…)不起作用!
我正在编写一个Python函数,将一个文件列表的扩展名改为另一个扩展名,比如txt改为rar,这只是一个空闲的例子.但我有个错误.代码是:import os def dTask(): #Get a f ...
- C++的友元函数,友元类及#pragma once的作用
把代码都放最后吧 友元函数的作用: 可以访问该类的私有属性 但在类的外面定义的时候没有"类::" 所以该友元函数不属于该类 友元函数的意义: C++友元函数_Bussy的博客-CS ...
- C/C++函数名称修饰规则及extern C的作用(函数名压扎)
一.函数名称修饰规则 函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型.LINK程序或其他工具有时需要指定函数的名字修饰来定位函数的正确位置 ...
- C语言函数中的3个点 ...有什么作用
转载于网友的一片文章,写的很好! 标准库提供的一些参数的数目可以有变化的函数.例如我们很熟悉的printf,它需要有一个格式串,还应根据需要为它提供任意多个"其他参数".这种函数被 ...
- Python中动态编译函数compile(source, filename, mode, ......)参数filename的作用是什么?...
动态编译函数compile调用语法如下: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) 其中的fi ...
- python内置函数range(a、b、s)的作用_python中,内置函数range(a,b,s)的作用是产生一个整数序列,从a到b....
python中,内置函数range(a,b,s)的作用是产生一个整数序列,从a到b. 答:错 在生物性污染中范围最广.危害最大的污染是微生物的污染.(?) 答:对 中国大学MOOC: Which of ...
最新文章
- 十五、linux 注册字符类设备和生成节点
- Acwing第 28 场周赛【完结】
- 02.es的节点发现和集群构建
- OpenFOAM安装+ParaView安装+环境配置(deb直接安装详细记录-Ubuntu14.04+OpenFOAM4.1)
- 【操作系统】进程与程序的比较
- 要成为一个 Java 架构师得学习哪些知识?
- 携号转网可能只会叫好不叫座
- html日历菜鸟,菜鸟第一次发代码 -- JS日历
- php语言中不能包含html标签,在邮件主题中包含html标签[PHP]
- java数字处理_Java数字处理类(上)
- Handlebars 和 angularjs 之间的区别
- 手把手教你在 SpringBoot 自定义参数解析器
- Linux 命令 | 常用命令之 cut
- 关于Kurento 和 WebRTC-Kurento学习(一)
- 详解MYSQL数据库密码的加密方式及破解方法(1)
- php安装扩展错误:Cannot find config.m4. Make sure that you run /usr/local/bin/phpize in the top level sourc
- 现代循环神经网络-1.门控循环单元(GRU)【动手学深度学习v2】
- first cdsn day
- HTML生日快乐代码 (粉色主题)(HTML5+CSS3+JS)520表白代码/七夕情人节网页/告白/求婚/生日快乐
- 几款适合vue移动端的第三方小组件