我想试验一个计算汇编指令长度的代码是否正确,因而写了如下code进行验证,但结果非常奇怪

#include <stdio.h>
#include <Windows.h> int add(int a,int b)
{
return a+b;
} extern ULONG GetOpCodeSize(PVOID Start); int main(int argc,char* argv[])
{
int c = add(1,2);
PVOID pFunc = (void*)add;
ULONG ulResult = GetOpCodeSize(pFunc);
return 0;
}

发现,返回的汇编指令长度等于5,然而,反汇编看到add的函数体为:

明显第一条指令是长度等于1。

debug发现:pFunc != add !!,而在pFunc地址处的指令如下:

原来VC++ debug模式下在调用函数之前需要通过一个中转,原因在于VC++的Incremental Link :

什么是Incremental Link Table呢?

假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占 0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call 到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去。这样的好处是,当一个函数入口地址改变时,只要修改 ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文件会稍大稍慢,Release版不会用上ILT。

最后disable Incremental Link 之后,结果是1,正确!

最新文章

  1. 软件工程线上课程(C语言实践篇)学习心得总结
  2. PHP基于websocket实时通信的实现—GoEasy
  3. Redis-cluster集群【第二篇】:redis持久化
  4. php 二维数组(没啥技术含量)
  5. 反射认识_02_反射成员变量Field
  6. php大力力 [002节]mac php环境安装,mamp安装 ,phpMyAdmin启动
  7. SQL SERVER 2008 R2 SP3 发布
  8. hdoj 5301 Buildings
  9. 20141109--SQL 练习题-1
  10. ORA-19809: 超出了恢复文件数的限制
  11. TDirectory.Delete 创建删除目录简单示例
  12. RSA加密算法正确性证明
  13. 【spoj LCS2】 Longest Common Substring II
  14. 同步文件的利器-rsync
  15. 标准IO:常用函数集合
  16. 修改CUSTOM.PLL文件调用客户化FORM&amp;修改标准FORM
  17. yii批量插入的方法
  18. 深入理解Fabric环境搭建的详细过程
  19. bootstrap 失效的原因
  20. MooFest POJ - 1990 (树状数组)

热门文章

  1. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.2.安装 cvuqdisk 软件包
  2. fedora25安装和docker-ce_清华源
  3. Jenkins+Maven+Gitlab+Nexus持续集成环境搭建
  4. Redis使用记录
  5. __block 和__weak 区别及使用
  6. python--web项目
  7. vb调试dll
  8. 转:C#中Monitor对象与Lock关键字的区别分析
  9. 使用CSS3实现响应式标题全屏居中和站点前端性能
  10. atitit.跨语言实现备份mysql数据库&#160;为sql文件特性&#160;api&#160;兼容性java&#160;c#.net&#160;php&#160;js