对一段有趣代码分析,你确定不来看看吗?

简介:大家好我是小江,放假的我在家实在是太无聊了,经常看别人博客文章也学到了不少知识,所以呢我决定自己弄了个博客来记录下自己的点点滴滴,在写文章的同时我会

尽量给大家写的详细点,把一些知识带给初学者,一起学习。

 

 

好了废话不多说了  我们直接进入主题,最近在一个论坛看到一个简单而又有趣的程序

代码如下:

#include <stdio.h>

int main()

{

  const short int c1 = 49920;

  const int c2 = 1073742008;

  int (*pf)() = (int (*)())&c2;

  printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);

  return 0;  

}

==========================这是一条华丽的分割线================================

我相信有大部分人都不理解这段代码的运行原理;

这段代码丢进VC++里面的运行结果是  :)

Turbo3.0中 这段代码是显示的结果是 Abnormal program termination(程序异常终止)

这里每个编译器的字节都是不同的 不如说Turbo3.0 short(短整型) 内存占用字节为:2B

VC++short 占用的字节为 4B int 的大小是一样的。

本次分析采用的编译器是VC++6.0

分析过程:

我们先从const(限定符) 开始吧;

const short int c1 = 49920;  

const int c2 = 1073742008;

这是两个局部变量 我们将它转换为16进制,用于后面的分析

C1=0xC300C2=0X400000b8

我们再来看看它们各自在内存的地址

 

C1地址为:0019FF3CC2=0019FF38;我们可以很清楚的看到c2c1的字节数为4B

这两个变量占据了连续的空间,这里给变量赋值后,从0x0019ff38开始内存单元的存储字节码为:B8 00 00 40 00 C3

对应的汇编码为:0040102E   mov         dword ptr [ebp-8],400000h  看下图

 

我们继续分析下一句

int (*pf)() = (int (*)())&c2;

   (int (*)());这里定义了一个函数指针 参数为NULL 而且返回值为int类型,这里的函数指针pf指向上面的汇编码,这就是这段语句的执行过程

 

接着分析下面 printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);

 *(char*)pf()-19 这段代码分析:刚刚我们函数指针pf() 是指向汇编码0x400000,然后(char*)再把汇编码转换成字符型指针来指向它的地址,最后在用他的地址减去个19然后再取这个地址的值,因为char在内存占用的字节数位1B因此从这个地址取一个字节。*(char*)pf()-19 其实就是从0x400000内存地址取出的字节内容再减去19

接下来的一句:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49

下面我们打开编译器找到0x400000的地址以及字节内容 如图

 

熟悉PE文件结构的朋友一定知道,对于exe文件0x400000是内存加载的基地址。

也就是说,0x400000 字节的内容对应的是0x4D,0x400001 字节的内容对应的是0x5A.

这是我们常说的pe文件起始的两个字节,"MZ"

 

0x400000地址=0x4D

0x400001地址=0x5A

刚刚上面说到

①:*(char*)pf()-19 其实就是从0x400000内存地址取出的字节内容再减去19

②:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49

 

 

 

①:0x4D-19=58

②:0x5A-49=41

 

最后按%c输出得到的结果是::)

 

别看代码少,这段代码知识点应用还是比较广泛的。

             这段代码就分析到这里了,不喜勿喷,最后谢谢大家的阅读。

 

 

posted @ 2017-06-15 14:30  小江。  阅读(881)  评论(1编辑  收藏  举报