计算机系统基础实验报告学院信电学院专业计算机班级1401学号140210110姓名段登赢实验时间:一、实验名称:程序的编译和链接二、实验目的和要求:(1)实验目的:对实验步骤中给出的源程序进行编辑、编译、链接,调试,熟悉开发环境、掌握开发和调试的基本过程以及工具。(2)实验要求:说明你做实验的过程(重要步骤用屏幕截图表示);提交源程序和可执行程序;分析并回答问题。三、实验环境(软、硬件):要求:详细描述实验用的操作系统,源代码编辑软件,相关硬件环境及所使用的GCC编译器的信息。四、实验内容:(1)分析同一个源程序在不同机器上生成的可执行目标代码是否相同。提示:从多个方面(如ISA、OS和编译器)来分析。(2)你能在可执行目标文件中找出函数printf()对应的机器代码段吗?能的话,请标示出来。(3)为什么源程序文件的内容和可执行目标文件的内容完全不同?实验步骤:1、以下程序实现了排序和求和算法,程序源码如下图所示。请根据提供的图片输入源程序文件,并保存为相应的.c和.h文件。bubblesort.h:bubblesort.c:add.h:add.c:printresult.h:printresult.c:main.c:2、将源程序文件进行预处理、编译、汇编和链接,以生成可执行文件。(1)使用gcc直接生成可执行文件gcc-omainmain.cbubblesort.cadd.cprintresult.c(2)首先生成可重定位目标文件(.o文件),再链接成可执行文件。首先,使用gcc–c……命令将所有.c文件编译成.o文件(可以用-o选项命名输出的可重定位目标文件),然后再用ld命令进行链接,以生成可执行目标文件。(用ld命令链接时要包含很多系统库,可以用gcc–vmain.c来查看系统链接需要哪些库,把collect2换成ld,生成的/tmp/ccBCU0rh.o即为mian.c编译出来的main.o文件,删掉该句替换成以下命令:-omainmain.obubblesort.oadd.oprintresult.o-emain)ld-omainmain.obubblesort.oadd.oprintresult.o-emain--sysroot=/--build-id--eh-frame-hdr-melf_i386--hash-style=gnu--as-needed-dynamic-linker/lib/ld-linux.so.2-zrelro/usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crt1.o/usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crti.o/usr/lib/gcc/i686-linux-gnu/4.8/crtbegin.o-L/usr/lib/gcc/i686-linux-gnu/4.8-L/usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu-L/usr/lib/gcc/i686-linux-gnu/4.8/../../../../lib-L/lib/i386-linux-gnu-L/lib/../lib-L/usr/lib/i386-linux-gnu-L/usr/lib/../lib-L/usr/lib/gcc/i686-linux-gnu/4.8/../../..-lgcc--as-needed-lgcc_s--no-as-needed-lc-lgcc--as-needed-lgcc_s--no-as-needed/usr/lib/gcc/i686-linux-gnu/4.8/crtend.o/usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crtn.o上述过程如下图所示:3、使用OBJDUMP命令进行反汇编(请自行查阅OBJDUMP命令的使用方法)例如,可使用“objdump–S”命令进行反汇编objdump–Smain.o:将main.o进行反汇编4、使用GDB命令进行各种调试(GDB命令参见教材附录C,也可自行查阅网上相关文档)调试之前首先用“gcc–g”命令生成调试信息,否则调试失败。gcc-g-omainmain.cbubblesort.cadd.cprintresult.cgdbmain要求用各种GDB命令对程序进行调试(例如用inforegisters查看寄存器内容)。五、实验结果及分析:实验结果:(1)分析同一个源程序在不同机器上生成的可执行目标代码是否相同。提示:从多个方面(如ISA、OS和编译器)来分析。答:不相同,因为一:总线的条数有区别,有16位,32位,64位总线结构,导致并行一次传输的数据不会一致,二:操作系统的不同,有Linux系统,Windows系统,mcos系统之分,导致程序才汇编和链接时的ELF表不会完全相同,三:从编译器来说,有gcc,vsC++之分,而不同的编译器在数据的对齐方面,库函数源文件方面,符号表创建和解析方面不会完全相同。所以导致在不同机器上生成的可执行代码不相同。(2)你能在可执行目标文件中找出函数printf()对应的机器代码段吗?能的话,请标示出来。答:不能,因为printf()在动态库libc.so.中,而这个库是动态链接库,所以程序在链接时并不把这个库的函数的机器码链接可执行程序中,而是在执行程序的时候才加载进来。所以不能找到printf()函数。(3)为什么源程序文件的内容和可执行目标文件的内容完全不同?答:因为源文件是一种用高级语言编写的文件,它的主要作用是便与程序员理解代码的逻辑关系。而可执行文件是一种给机器识别的文件,现在的计算机依旧是二进制运算,很明显它无法识别高级语言,而编译器的作用是就是将高级语言转换成机器语言,所以源程序文件的内容和可执行目标文件的内容不会一样。六、实验心得通过这次实验让我知道了程序的链接过程和执行过程,明白了静态链接库和动态链接库的不同之处,知道了程序生成过程中需要建立符号表和还要解析符号表,让我了解了在定义变量时需要注意的事项。让我对从高级语言到机器语言之间的转换更加的清晰了,同时也让自己更加熟悉Linux系统下的gnu调试的方法,反汇编后的源码查看。总之,收获颇多。