计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 人工智能专业
学 号 2022111813
班 级 2203602
学 生 闫冬
指 导 教 师 吴锐
计算机科学与技术学院
2024年5月
本篇论文详细讲述并演示了如何将一个C语言程序转换为可执行文件,并解析了每一个中间步骤产生的文件。以hello.c程序为例,本文讲述了从hello.c到hello过程中,预处理、编译、汇编、链接、进程管理、存储管理、I/O管理一系列中间步骤,演示了每一步的操作与结果,阐述了计算机系统的原理与体系结构,使人们体会到计算机系统的乐趣与精妙之处,使读者更加深入理解和掌握C程序编译与执行过程
关键词:计算机系统;编译;链接;进程;存储
目 录
第1章 概述
1.1 Hello简介
P2P:from Program to Process。当编译好一个hello.c的C语言程序,它将作为程序一个文本存储。运行这个程序时,由编译器驱动程序启动,读取hello.c文件,进行预处理,得到另一个C语言程序hello.i文件;然后由编译器对hello.i进行编译,得到一个汇编语言程序hello.s。之后将汇编程序交由汇编器进行汇编,得到一系列机器语言指令,并将这些机器语言指令打包成可重定位目标程序,并将其存入到hello.o(二进制)文件中。最后由链接器进行链接,就得到了可执行目标文件hello。接下来计算机就可以直接运行这个hello文件了。在计算机的shell中,OS为hello创建子进程,这样,在计算机系统中hello就有了自己的独立的进程,在这个进程中hello便可以运行了。
020:from Zero-0 to Zero-0。程序并不是一开始就在内存空间中的,也就是一开始为0。OS为通过fork()函数为hello创建了一个子进程,然后调用execve()函数加载并运行hello程序,OS为hello程序开辟一个块虚拟内存,并将程序加载到虚拟内存映射到的物理内存中。当程序执行完,shell父进程回收这一子程序,内核将回收为该程序的开辟的内存空间与数据,此时又变为0。
1.2 环境与工具
1.2.1 硬件环境
X64 CPU; 2GHz; 16G RAM; 512GHD Disk
1.2.2 软件环境
Windows11 64位; VirtualBox 7; Ubuntu20.04
1.2.3 开发工具
Visual Studio Code; vi/vim/gcc/objump等
1.3 中间结果
hello.i 对hello.c文本文件预处理得到的文本文件
hello.s 经过cc1编译后得到的汇编语言文件
hello.o 经过as汇编后得到的可重定位目标二进制文件
hello 可执行目标文件
hello.asm hello.o的反汇编文件
hello1.asm hello的反汇编文件
1.4 本章小结
本章对hello程序的P2P与020流程进行简要的概述,并对本实验的软硬件环境与开发工具进行介绍,最后介绍了本实验过程中生成的中间结果文件的名称与作用。
第2章 预处理
2.1 预处理的概念与作用
2.1.1预处理的概念
C语言文件的预处理发生在实际编译之前。预处理器(cpp)处理代码文件中的预处理指令,将它们转换为实际代码中的内容,这些指令以#开头(例如#define,#include……),同时,预处理器还会删除程序中注释和多余的空白字符。
2.1.2预处理的作用
1.宏定义(#define来定义宏):宏定义提供了一种方便的方式来创建可重用的代码片段,简化代码编写与维护;
2.文件包含(#include来包含其他文件):允许程序员重用代码,特别是库,无需重复编写;
3.条件编译(#ifdef,#if,#else……来根据条件包含或排除代码):允许根据编译时的条件编译不同的代码,可用于调试、平台特定代码或版本控制;
4.错误信息(#erro来在编译时输出错误信息):在不符合特定条件时,强制编译失败,通常用于确保编译环境的正确性;
5.行控制(#line来指定文件名和行号,改变编译器报告错误和警告时显示的行号):在处理大型文件或从多个源文件生成单个输出文件时,有助于调试。
6.可移植性:通过预处理指令,如#ifdef, #ifndef, 可以定义或取消定义宏,以适应不同的编译环境或平台,提高代码的可移植性,使代码能够在不同的系统和编译器上运行。
7.编译时间计算:预处理器可以执行简单的算术运算和字符串操作,如#(字符串化)和##(标记粘贴)运算符,允许在编译时进行计算和操作,减少运行时的开销。
2.2在Ubuntu下预处理的命令
预处理的指令:gcc -E hello.c -o hello.i
2.3 Hello的预处理结果解析
打开hello.i文件,发现代码有3000多行,比源文件hello.c多了许多,这是因为预处理后,#预处理命令将头文件,宏定义,特殊符号等等插入到了hello.c中
文件中有许多typedef,是对数据类型(eg:signed int,unsigned char……)的定义,还有extern外部符号,这些都源于头文件<stdio.h>,<unistd.h>, <stdlib.h>,预处理器不会对头文件中的内容做计算与变化,只会简单的进行复制与替换。
2.4 本章小结
本章介绍了在Linux环境中,通过gcc -E hello.c -o hello.i指令,对hello.c进行预处理得到hello.i文件的过程,并详细解析了得到的hello.i预处理结果