函数开始处的MOV EDI, EDI的作用
调试程序调试到系统库函数的代码时,总会发现系统函数都是从一条MOV EDI, EDI指令开始的,紧接着这条指令下面才是标准的建立函数局部栈的代码。对系统DLL比如ntdll.dll进行反汇编,可以发现它的每个导出函数都是如此,并且每个导出函数开始处的MOV EDI, EDI上面紧接着5条NOP指令。比如在WinDbg中查看TextOutA周围的代码:
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,是出于效率的考虑。
函数开始处的MOV EDI, EDI的作用的更多相关文章
- Win32API起始处的mov edi, edi与用户空间InlineHook
在x86平台上,无论是在调试器中跟到系统DLL中时,还是反汇编某个系统DLL时,经常会发现很多API的第一条汇编指令都是mov edi, edi.根据经验来讲,C函数的汇编形式,应该是首先push e ...
- Delphi函数的out、var等关键字的作用,和使用场景
问题描述 Delphi函数的out.var等关键字的作用,和使用场景 Delphi函数的out.var等关键字的作用,和使用场景,我知道var是作为传值调用,但是像out这个关键字又是什么作用呢? 解 ...
- [反汇编]函数开始部分利用mov ebx,esp找到返回地址(_KTRAP_FRAME结构)
我们理解call原理,首先将返回地址压入栈中,之后执行调用. 因此,在一个函数开始部分,esp依旧是上一个栈帧的esp,此时esp指向返回地址. 这就意味着使用 mov ebx,esp,之后 [ebx ...
- vscode跳转到函数定义处
需要安装对应语言的插件,帮助-欢迎使用,安装javascript, php php还需要安装php7, 到官网https://windows.php.net/download#php-7.2 下载解压 ...
- 一句话改变TWinControl控件的left坐标的前世今生(入口函数是SetBounds,然后调用SetWindowPos起作用,并发消息更新Delphi的left属性值)
Delphi的重要属性,主要是Enable, Visible, Color, left等等.这里分析left,因为TWinControl里有些覆盖函数的原因,虽然起点都是TControl.SetLe ...
- Python中动态编译函数compile(source, filename, mode, ......)参数filename的作用是什么?
动态编译函数compile调用语法如下: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) 其中的fi ...
- C语言函数中的3个点 ...有什么作用
标准库提供的一些参数的数目可以有变化的函数.例如我们很熟悉的printf,它需要有一个格式串,还应根据需要为它提供任意多个"其他参数".这种函数被称作"具有变长度参数表的 ...
- Windows系统调用中API的3环部分(依据分析重写ReadProcessMemory函数)
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API的3环部分 一.R3环API分析的重 ...
- 汇编之 eax, ebx, ecx, edx, esi, edi, ebp, esp??
一般寄存器:AX.BX.CX.DXAX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器 索引暂存器:SI.DISI:来源索引暂存器,DI:目的索引暂存器 堆叠.基底暂存器:SP.BP ...
随机推荐
- JS window对象取消计时器clearInterval() clearInterval() 方法可取消由 setInterval() 设置的交互时间。
取消计时器clearInterval() clearInterval() 方法可取消由 setInterval() 设置的交互时间. 语法: clearInterval(id_of_setInterv ...
- 在VSCode中使用Markdown
前言 最近在学习使用Markdown语法,尝试使用了"MarkdownEditor"."Sublime Text3"."VSCode"这三种 ...
- leetcood学习笔记-113-路径总和 II
题目描述: 参考后的提交: class Solution(object): def pathSum(self, root, sum): """ :type root: T ...
- chkconfig 与 systemctl
chkconfig命令 主要用来更新(启动或停止)和查询系统服务(service)的运行级信息,用于维护/etc/rc[0-6].d目录的命令行工具. chkconfig -–add httpd 增加 ...
- 用pytorch进行CIFAR-10数据集分类
CIFAR-10.(Canadian Institute for Advanced Research)是由 Alex Krizhevsky.Vinod Nair 与 Geoffrey Hinton 收 ...
- JS对象的可枚举属性和不可枚举属性
昨天在写文章(转载)的时候发现了有些对象的方法是分可枚举性和不可枚举性的.简单的查了一下资料,今天来捋一捋啥是对象的可枚举啥是不可枚举. 可枚举性: 对象的每一个属性都有一个描述对象,用来描述和控制该 ...
- Comparison of FastText and Word2Vec
Comparison of FastText and Word2Vec Facebook Research open sourced a great project yesterday - fas ...
- 剑指offer——26树的子结构
题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 题解: 注意,所谓的子结构,是树的形状和值相同,并非判断B是不是A的一部分[如果是这样,那就是 ...
- 20140329 自由 youtube
1.人生入戏,全靠演技:人生苦短,必须性感 2.youtube修改用户名 3.使用代理软件修改了IE的代理导致上不了网
- Day 9 :初识函数
Python函数:1.函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 2.函数能提高应用的模块性,和代码的重复利用率. Python提供了许多内建函数,比如print().但你也可 ...