计算机系统基础实验报告linux下gcc编译的四个步骤
学院 信电学院 专业 计算机 班级 1401
学号 1402***** 姓名 段登赢 实验时间:
一、实验名称:程序的编译和链接
二、实验目的和要求:
(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 -o main main.c bubblesort.c add.c printresult.c
(2) 首先生成可重定位目标文件(.o 文件),再链接成可执行文件。
首先,使用gcc –c …… 命令将所有.c 文件编译成.o 文件(可以用-o 选项命名输出的可重定位目标文件),然后再用ld 命令进行链接,以生成可执行目标文件。
(用ld命令链接时要包含很多系统库,可以用gcc –v main.c来查看系统链接需要哪些库,
把collect2 换成ld,生成的/tmp/ccBCU0rh.o 即为mian.c 编译出来的main.o 文件,删掉该句替换成以下命令:-o main main.o bubblesort.o add.o printresult.o -e main)
ld -o main main.o bubblesort.o add.o printresult.o -e main --sysroot=/ --build-id
--eh-frame-hdr -m elf_i386 --hash-style=gnu --as-needed -dynamic-linker /lib/ld-linux.so.2 -z
relro /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 –S main.o:将main.o进行反汇编
4、使用GDB命令进行各种调试(GDB命令参见教材附录C,也可自行查阅网上相关文档)
调试之前首先用“gcc –g”命令生成调试信息,否则调试失败。
gcc -g -o main main.c bubblesort.c add.c printresult.c
gdb main
要求用各种GDB命令对程序进行调试(例如用info registers 查看寄存器内容)。
五、实验结果及分析:
实验结果:
(1)分析同一个源程序在不同机器上生成的可执行目标代码是否相同。
提示:从多个方面(如ISA、OS 和编译器)来分析。
答:不相同,因为一:总线的条数有区别,有16位,32位,64位总线结构,导致并行一次传输的数据不会一致,二:操作系统的不同,有Linux系统,Windows系统,mc os系统之分,导致程序才汇编和链接时的ELF表不会完全相同,三:从编译器来说,有gcc,vs C++之分,而不同的编译器在数据的对齐方面,库函数源文件方面,符号表创建和解析方面不会完全相同。所以导致在不同机器上生成的可执行代码不相同。
(2)你能在可执行目标文件中出函数printf ()对应的机器代码段吗?能的话,请标示出来。
答:不能,因为printf()在动态库libc.so.中,而这个库是动态链接库,所以程序在链接时并不把这个库的函数的机器码链接可执行程序中,而是在执行程序的时候才加载进来。所以不能到printf()函数。
(3)为什么源程序文件的内容和可执行目标文件的内容完全不同?
答:因为源文件是一种用高级语言编写的文件,它的主要作用是便与程序员理解代码的逻
辑关系。而可执行文件是一种给机器识别的文件,现在的计算机依旧是二进制运算,很明显它无法识别高级语言,而编译器的作用是就是将高级语言转换成机器语言,所以源程序文件的内容和可执行目标文件的内容不会一样。
六、实验心得
通过这次实验让我知道了程序的链接过程和执行过程,明白了静态链接库和动态链接库的不同之处,知道了程序生成过程中需要建立符号表和还要解析符号表,让我了解了在定义变量时需要注意的事项。让我对从高级语言到机器语言之间的转换更加的清晰了,同时也让自己更加熟悉Linux系统下的gnu调试的方法,反汇编后的源码查看。总之,收获颇多。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论