代码改变世界

C++学习笔记 2014-10-11

2014-10-11 20:06  想打架的蜜蜂  阅读(159)  评论(0)    收藏  举报

1、编译器编译源代码后生成的文件叫做目标文件,目标文件从结构上讲,他是已经编译后的可执行文件格式,只是还没链接,有些符号和地址还没有做出调整,他也是按照可执行文件格式存储的。

2、目标文件的格式:

可执行文件格式,在Windows下是PE和Linux下的ELF,他们都是COFF格式的变种。目标文件就是源代码进行编译后但是未进行链接的那些中间文件(Windows下是.obj和Linux下的.o),动态链接库(Windows下是.dll和Linux下的.so)以及静态链接库(Windows下是.lib和Linux下的.a)都是可执行文件存储,静态链接库稍不同,他是将很多目标文件的捆绑在一起形成一个文件,再加上一些索引。

3、目标文件是什么样子的?

目标文件中的内容有编译后的指令代码、数据,还包括链接时所需要的一些信息,如符号表、调试信息、字符串等。目标文件将这些文件按照不同的属性,以“节”的形式存储,,有时候也叫“段”,他们都表示一个一定长度的区域。程序源代码编译后的机器指令经常放在代码段,代码段常见名称由“.code”或者".text",已初始化的全局变量和局部静态变量经常放在数据段".data"里面,未全局话的放在".bass"中,只是预留位置而已,因没有内容,所以它在文件中不占用空间。

4、程序段和数据段分开存放的好处

1)由于数据区对于进程来说是可读可写的,而指令区只是可读的,所以权限应该被分开设置,故分开存放

2)对于现代cpu,有着强大的缓存cache体系,程序必须尽量提高缓存的命中率,指令区和数据区的分离,有助于提高程序的局部性,现代cpu一般被设成数据缓存和指令缓存,分开虽cpu的缓存命中率提高有好处。

3)当系统中运行多个该程序的副本时,他们的指令就是一样的,所以内存中只需要保存一份改程序的指令部分。程序里面带有的图标、图片、文本等资源也可以共享的。当然每个副本进程的数据区域是不一样的,他们是进程私有的

现在用Gcc来编译这个文件,gcc -c hello.c(-c表示只编译不链接)   然后再用binutils的工具objdump来查看object内部的结构用命令 objdump -h hello.o 

参数-h就是把elf文件的各个段的基本信息打出来。-x能把更多信息打印出来。

下面讲讲具体内存分布:以下面的源程序

这个程序段的数量有代码段、数据段、bss段还有只读数据段、注释信息段、堆栈提示段,如下:

有一个size的命令,他可以用来查看代码段、数据段、bss段的长度

代码段:

objdump 的 -s 参数可以将所有段的内容以十六进制的方式打印出来, -d参数可以将所有包含指令段反汇编。

Contents of section .text的数据以十六进制方式打印出来的内容,总共Ox5b字节,最左边是偏移量,中间4列是十六进制内容,最右边一列是.text段的ASCII码,.text段里面所包含的正是SimpleSection.c里两个函数funcl()和main()的指令,.text段的第一个字节“0x55”就是funcl()函数的第一条push %ebp指令,而最后一个字节0xc3正是main()函数的最后一条指令 ret。

数据段和只读数据段

.data段保存的是已经初始化了得全局静态变量和局部静态变量。即代码中的global_init_varabal与static_var,这两个变量每个4个字节,共8个,所以.data段大小为8个字节。

的,所以放在.data段中。