《计算机系统基础》大作业:程序人生

目录

摘要

本文通过hello从编写源文件hello.c到执行hello中的四个步骤(预处理、编译、汇编和链接)展开进行了讨论,并在Linux下利用相关工具,如objdump、readelf和edb,依次解读了各个步骤中所生成的中间文件(hello.i、hello.s、hello.o和hello)。以此为基础,总结并讨论了hello的进程管理、存储管理和IO管理中的相关内容。文章的各个部分又分别对应了《计算机系统基础》课程中的相关内容,既是对课程内容的一次复习,也能够对课程的内容形成一个整体性、框架性的认识,加深了对本门课程的理解。

关键词:计算机系统;hello;预处理;编译;汇编;链接;进程;虚拟内存;I/O

第1章 概述

1.1 Hello简介

多年以后,Hello Junior上校站在SIGINT信号面前,准会想起父亲Hello带他去参观虚拟地址空间的那个遥远的下午。当时,对计算机系统还不怎么了解,一个个功能单元都整齐的排列着,缓存里空荡荡的,顺着数据流望去,几个功能单元早已不堪重负,但还是有几个还光洁如新。这个符号还是新引用的,人们只是能叫出名字,大家只能用手指指点点却不知道它具体在何处。每年三月,衣衫褴楼的程序员都要守在系统旁边,大声疾呼,向大家介绍他们新发布的库。他们首先带来的是libc.so。一个身躯高大的程序员,自称丹尼斯里奇,满脸络腮胡子,手指瘦得像鸟的爪子,向观众出色地表演了他所谓的奇迹。他手里拿个大家伙,走过来走过去,大家都惊异地看见,本来大家只叫的出名字的符号拼了命想挣脱出来,一些看似丢失的东西兀然出现,整整齐齐地立在那些符号之前。“这些符号也是有生命的,”他用刺耳的声调说,“只需要使用链接器把它们唤醒!”
——以上内容仿写《百年孤独》开头,纯属娱乐。

本次大作业完整地进行了hello.c由预处理、编译、汇编和链接为hello可执行目标文件的过程。在完成大作业的过程中,对这四个步骤的概念进行了回顾并且对各个步骤中产生的文件进行了解析。之后又分别对hello的进程管理、存储管理和I/O管理过程进行了回顾与分析。完成整个大作业耗时若干天,而对hello来说却是它坎坷的一生。

1.2 环境与工具

硬件环境:i7 6700HQ;16G内存;512G硬盘
软件环境:Windows10 64位;VMware虚拟机下运行Ubuntu19.02
开发工具:Ubuntu下使用gcc、objdump、readelf和edb

1.3 中间结果

hello.i:对hello.c进行预处理时产生的中间文件。作用:(1)将源文件中以include格式包含的文件复制到编译的源文件中(2)用实际值替换用#define定义的字符串(3)根据#if后面的条件决定需要编译的代码。
hello.s:对hello.i进行编译时产生的中间文件。作用:生成汇编语言程序。
hello.o:对hello.s进行汇编时产生的中间文件。作用:通过汇编器翻译为机器指令的过程,同时这些机器指令被打包为可重定位目标程序的格式。
hello:由hello.o链接生成的可执行目标文件。作用:完成编写hello.c时所设计的功能。

1.4 本章小结

本章中,对hello的一生进行了简单地介绍,并列出了为完成本次大作业而使用的环境与工具。从hello.c到hello可执行目标文件的几个中间文件及其作业也做了简单地介绍,这些内容将在后续的章节中进行较为详细地讨论。

第2章 预处理

2.1 预处理的概念与作用

C语言中引入了预处理和条件编译等概念大大地增强了代码的移植性强以及代码的修改方便等方面的性能。在C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令。预处理命令属于C语言编译器,而不是C语言的组成部分。通过预处理命令可扩展C语言程序设计的环境。

C语言预处理的工作是在编译器对源代码编译之前进行的。查询相关资料可知,预编译的主要作用有:(1)将源文件中以include格式包含的文件复制到编译的源文件中(2)用实际值替换用#define定义的字符串(3)根据#if后面的条件决定需要编译的代码

2.2在Ubuntu下预处理的命令

所使用的命令为gcc -m64 -no-pie -fno-PIC -E -o hello.i hello.c。在Ubuntu下操作时的截图如下所示,执行完指令之后文件夹中出现了hello.i文件。
在这里插入图片描述

2.3 Hello的预处理结果解析

预处理文件hello.i源于hello.c源文件,hello.c源文件中的内容如下图所示。
在这里插入图片描述
可以看到,源文件的开头处为一些注释,在main函数之前还存在一些以#include开头的指令。根据2.1部分中介绍的预处理的作用可知,预处理的过程将会对这些include包含的头文件进行处理。这些处理的过程在hello.i中均有体现,如下图所示。
在这里插入图片描述
在这里插入图片描述
还有一点值得注意的是,虽然源文件hello.c中仅寥寥几行的代码,但是预处理后的文件hello.i中却有数千行的代码,比较难以对其全部内容进行阅读。因此,以上在hello.i中查找头文件相关信息的工作,只能够通过ctrl + F进行搜索完成。

2.4 本章小结

本章中对hello.c预处理至hello.i的过程进行了讨论,并对预处理的结果hello.i文件中的相关内容进行了解析。

第3章 编译

3.1 编译的概念与作用

根据大作业的要求可知,此处的编译是指由.i文件生成.s文件,即预处理后的文件经过词法、语法和语义分析后并进行相关的优化(如-Og、-O1等),生成汇编语言程序。但是似乎编译更广义一点儿的含义是指包含了预处理、编译、汇编和链接四个步骤的全过程的行为,如下图所示。需要根据上下文进行一定的区分。

在这里插入图片描述

3.2 在Ubuntu下编译的命令

所使用的命令为gcc -m64 -no-pie -fno-PIC -S -o hello.s hello.i。在Ubuntu下的操作截图如下所示,执行完该命令后可以发现文件夹中多出了一个hello.s的文件。
在这里插入图片描述

3.3 Hello的编译结果解析

虽然说大作业中提示,应分3.3.1~3.3.x等子章节按照类型和操作对hello.s中的语句进行说明,对此我有一些不同的看法。

查看PPT中的相关页面发现共有以下的几种类型:数据、赋值、类型转换、sizeof、算术操作、逻辑/位操作、关系操作、数组/指针/结构操作、控制转移和函数操作如此多的类,而查看hello.s文件中却发现总共仅仅有53行。因此,我认为将对hello.s的解读分解成较多的板块虽然说内容比较详细,但是可能会造成对hello.s该文件中的内容缺乏一个整体性的理解。在本次大作业中,我将采用“从main函数开始,一步一步地对照hello.c源文件来解读hello.s中涉及到的语句,并在解读的过程中穿插一些课程中曾经学过的知识”这样一个思路完成本章节的撰写。

从main函数开始,hello.s中部分语句的截图如下所示。
在这里插入图片描述
可以看到,main函数中首先执行了pushq %rbp和movq %rsp, %rbp。这两条语句真的是再熟悉不过了,在学习课程第三章“程序的机器级表示”过程中每次调用一个函数就一定会出现这两条语句。%rbp为一个“被调用者保存寄存器”,在此程序中被调用者即为main函数。对于此类寄存器,被调用者可以采用两种策略进行处理:(1)不使用(2)将这类寄存器中的值压栈后正常使用,被调用者结束后将其弹栈还给调用者。此程序中后续要使用%rbp来访问函数中的局部变量,不得不使用该寄存器,因此对%rbp采用的是第二种处理方法。寄存器%rsp为栈指针,始终指向栈的顶端。movq %rsp, %rbp语句将%rsp的值赋给%rbp,而此时栈顶处存放的是旧的%rbp的值,因此可以这么理解:新的%rbp的值指向的是旧的%rbp的值在栈中存放的位置,如下图所示,该示意图也可以用来理解堆栈中局部变量的存放位置,马上就要讲到。
在这里插入图片描述
之后的几条指令为:subq 32, %rsp、movl %edi, -20(%rbp)和movq %rsi, -32(%rbp)。将%rsp的值减去一个立即数(用$符号表示)32,实际上是在栈中分配出大小为32字节的空间,用来存放被调用函数中所建立的局部变量,如上图所示。为局部变量分配完空间之后,将%edi的值存放在堆栈中%rbp-20的位置,将%rsi的值存放在堆栈中%rbp-32的位置。可以看出,堆栈中查找局部变量是通过%rbp来进行的,而并不是使用%rsp栈指针。

然而,%edi和%rsi中存放的又是什么东西呢?这就涉及到函数中参数传递的相关内容了。如下图所示,向一个函数传递参数时,根据参数的顺序,从前往后分别由%rdi、%rsi、%rdx、%rcx、%r8和%r9进行(更多的参数通过栈来传递)。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值