第1章 概述
(0.5分)
1.1 Hello简介
1.1.1 hello.c的P2P(From Program to Process):
hello.c是一个在在linux环境下用c语言写成的一个高级c语言程序(源程序文件),即“Program”。具体代码如下图:
图1.1 hello.c源程序
程序指示用户,如果没有输入学号、姓名、秒数三个变量,就会打印该程序用法;而如果输入正确,就会按照用户的输入,每几秒打印用户的学号和姓名,一共执行八次。
在linux的命令行窗口中执行以下指令:
gcc -m64 -no-pie -fno-PIC hello.c -o hello
执行该指令后,系统会调用图1.2中的编译系统,生成名为hello的二进制可执行目标程序。而从hello.c到hello的“翻译”可分为以下四个阶段:
图1.2 编译系统
在shell中输入指令./hello 120L021925 刘馥淇 1,shell将获取argc、argv、envp三个参数,即argv[1]的内容是“120L021925”,argv[2]的内容是“刘馥淇”, argv[3]的内容是1。
经过cpp,ccl,as,ld的处理,逐步生成hello.i, hello.s, hello.o, hello文件,即Process,完成P2P的过程。
1.1.2 hello.c的O2O(From Zero-0 to Zero-0):
首先,调用fork()函数创建子进程,execve加载文件名后,调用启动代码设置栈,并将控制传给子进程。先删除当前虚拟地址的用户部分已存在的数据结构,为hello文件等创建新的区域结构,然后初始化程序计数器,使之指向代码区域的入口点。进入main函数后,CPU为hello分配时间片执行逻辑控制流。hello通过Unix I/O管理来控制输出。在hello进程终止之后会被回收,hello所有的痕迹将被删除,操作系统将控制权传回给shell,shell将等待下一个命令行输入。至此,hello.c完成“从无到无”的O2O过程。
1.2 环境与工具
软件环境:Windows 10 64位;Vmware16.2;Ubuntu20.03
硬件环境:Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz;2.80GHz;8.00G RAM;1TGHD Disk 系统类型 64 位操作系统, 基于 x64 的处理器
调试工具:CodeBlocks;gedit+gcc;
1.3 中间结果
hello.c:源程序文件;
hello.i:修改了的源程序;
hello.s:汇编程序文本文件;
hello.o:可重定位目标程序(二进制文件);
hello:可执行目标程序;
hello_asm.txt:hello的反汇编文件
1.4 本章小结
本章分别大致描述了hello.c的P2P和O2O的过程,并且列出了调试hello.c所用的软硬件环境以及调试工具,最后列出了编写本篇论文过程中所生成的所有文件名称与性质。
第2章 预处理
(0.5分)
2.1 预处理的概念与作用
概念:预处理阶段是指预处理器(cpp)根据以字符#开头的命令,修改原始的c程序的过程。比如hello.c中的#include <stdio.h>编译预处理指令就是告诉cpp读取系统头文件stdio.h的内容,并把它直接插入程序文本中。#include <unistd.h>与#include <stdlib.h>的作用同理。
作用:得到另外一个c程序文件,它通常以.i作为扩展名,即1.3中提及的hello.i。
2.2在Ubuntu下预处理的命令
预处理指令:cpp hello.c>hello.i 或gcc -E hello.c -o hello.i
2.3 Hello的预处理结果解析
打开生成的hello.i之后,如下图,hello.i仍是可以阅读的文本文件,但是通过观察行数可以发现,hello.i在hello.c的基础上增加了很多内容。在这里,预处理器读取系统头文件stdio.h的内容,并把它直接插入程序文本中,于是得到hello.i。
2.4 本章小结
本章以对hello的预处理操作为实例,充分展现了.c文件在执行预处理指令之后经历的操作与预处理后生成的结果。
第3章 编译
(2分)
3.1 编译的概念与作用
概念:编译是指编译器(ccl)将文本文件hello.i翻译成包含汇编语言程序的文本文件hello.s的过程,也就是将高级语言变成汇编指令的过程。
作用:生成汇编程序(文本文件)hello.s;词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。
3.2 在Ubuntu下编译的命令
如下图,输入编译指令:gcc -S hello.i -o hello.s
3.3 Hello的编译结果解析
3.3.1 数据
(1)字符串常量
图3.3.1 出现的字符串
作为printf函数的参数出现。
(2)局部变量
图3.3.2 局部变量示例
通过mov等操作,将局部变量储存在%rax,%rbx等寄存器中。
(3)全局函数main
对主函数main的声明如下:
图3.3.3 全局函数main的声明
3.3.2 赋值
这里举几个通过汇编指令来实现的赋值操作:
图3.3.4 通过mov指令实现的赋值操作
图3.3.5 含有立即数的赋值指令
图3.3.6 通过add指令实现的赋值操作
3.3.3 类型转换
如下图,用call指令调用atoi函数,将字符串中的数字转化为int型;
图3.3.7 类型转换示例
3.3.4 算术操作
hello.s中存在着加法和减法操作,具体如下:
图3.3.8 加法操作
图3.3.9 减法操作
3.3.5 关系操作
在hello.s中,两个数值大小关系的比较是通过comp指令和j跳转指令完成的,具体示例如下: