哈工大csapp大作业 程序人生 您所在的位置:网站首页 汇编语言反汇编指令的作用 哈工大csapp大作业 程序人生

哈工大csapp大作业 程序人生

2023-05-25 05:16| 来源: 网络整理| 查看: 265

计算机系统

大作业

题     目  程序人生-Hello’s P2P  

专       业 人工智能领域方向(2+X)

学     号     2021112522         

班   级       21WL021         

学       生        郭家合        

指 导 教 师        史先俊            

计算机科学与技术学院

2023年4月

摘  要

本文介绍了一个c语言程序“hello”是如何一步步地从.c文件开始,历经历经预处理、编译、汇编、链接的一系列步骤变成可执行文件,再经过shell的fork和execve变成一个进程,这就是hello的P2P(Program2Process)的过程。除此之外,本文还讨论了hello程序在运行时涉及到的进程管理,内存管理,io管理等过程。从可执行文件hello被执行前,内存中没有它的存在,到最后运行结束被shell回收进程,抹去它的痕迹,这就是hello的020过程。本文通过详细介绍这两个过程,解释linux中程序的运行原理和过程,加深我们对整个计算机系统的理解。

关键词:CSAPP;内存管理;编译;链接 ;汇编                           

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)

目  录

第1章 概述

1.1 Hello简介

1.2 环境与工具

1.3 中间结果

1.4 本章小结

第2章 预处理

2.1 预处理的概念与作用

2.2在Ubuntu下预处理的命令

2.3 Hello的预处理结果解析

2.4 本章小结

第3章 编译

3.1 编译的概念与作用

3.2 在Ubuntu下编译的命令

3.3 Hello的编译结果解析

3.4 本章小结

第4章 汇编

4.1 汇编的概念与作用

4.2 在Ubuntu下汇编的命令

4.3 可重定位目标elf格式

4.4 Hello.o的结果解析

4.5 本章小结

第5章 链接

5.1 链接的概念与作用

5.2 在Ubuntu下链接的命令

5.3 可执行目标文件hello的格式

5.4 hello的虚拟地址空间

5.5 链接的重定位过程分析

5.6 hello的执行流程

5.7 Hello的动态链接分析

5.8 本章小结

第6章 hello进程管理

6.1 进程的概念与作用

6.2 简述壳Shell-bash的作用与处理流程

6.3 Hello的fork进程创建过程

6.4 Hello的execve过程

6.5 Hello的进程执行

6.6 hello的异常与信号处理

6.7本章小结

第7章 hello的存储管理

7.1 hello的存储器地址空间

7.2 Intel逻辑地址到线性地址的变换-段式管理

7.3 Hello的线性地址到物理地址的变换-页式管理

7.4 TLB与四级页表支持下的VA到PA的变换

7.5 三级Cache支持下的物理内存访问

7.6 hello进程fork时的内存映射

7.7 hello进程execve时的内存映射

7.8 缺页故障与缺页中断处理

7.9动态存储分配管理

7.10本章小结

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

8.2 简述Unix IO接口及其函数

8.3 printf的实现分析

8.4 getchar的实现分析

8.5本章小结

结论

附件

参考文献

第1章 概述 1.1 Hello简介

P2P是指程序到进程(Program to Process),020是指程序从0开始,运行结束后又被删除回到0。

P2P:

程序从一个.c文件开始,首先经过预处理器cpp,进行预处理得到.i文件(执行宏替换等操作),之后用编译器ccl进行编译,得到.s文件(汇编语言),之后用汇编器as生成.o文件(可重定位文件),之后用链接器ld将它与它用到的库链接,得到可执行文件hello。我们在shell里执行命令,shell会fork一个子进程,调用execve,并映射虚拟内存,这就是hello.c这个program运行时得到的process

020:

在子进程中调用execve函数装载hello程序,将相关可执行文件中的段映射入虚拟内存。当该进程的时间片到达时,操作系统设置CPU上下文环境,并跳到程序开始处。程序执行完毕,shell回收这个子进程,完成hello相关内存的释放。hello本不存在于内存上,这个让hello映射到虚拟内存,并在最后被shell回收再次消失在内存上的过程就是hello的020过程。

1.2 环境与工具

硬件环境:Intel 11th Gen core i5-11400H @2.70GHz  16.0G RAM;512GHD Disk

软件环境:Windows10 64位 VMware Workstation16.0 Ubuntu 22.04.4 LTS 64位

开发工具:CodeBlocks 64位,vim,edb,gedit,gcc

1.3 中间结果

hello.i:C预处理器产生的一个ASCII码的中间文件,用于分析预处理过程。

hello.s:C编译器产生的一个ASCII汇编语言文件,用于分析编译的过程。

hello.o:汇编器产生的可重定位目标程序,用于分析汇编的过程。

hello:链接器产生的可执行目标文件,用于分析链接的过程。

hello.txt:hello.o的反汇编文件,用于分析可重定位目标文件hello.o。

hello2.txt:hello的反汇编文件,用于分析可执行目标文件hello。

hello.elf:hello.o的ELF格式,用于分析可重定位目标文件hello.o。

hello2.elf:hello的ELF格式,用于分析可执行目标文件hello

(第1章0.5分)

第2章 预处理 2.1 预处理的概念与作用

概念:预处理是指,预处理器cpp根据以字符#开头的命令修改原始的C 程序,将引用的所有库展开,得到一个完全展开的,完整的文本文件。

作用:预处理可以

1.文件包含:将#include引用的文件插入文本

2.宏替换:用#define和#undef添加和删除宏

3.条件编译:有选择地编译代码,实现版本控制等功能,如#if,#elif,#endif

4.编译器指令:用#pragma添加,如之前优化实验里的O2优化

5.#error,当遇到标准错误时,输出错误信息

2.2在Ubuntu下预处理的命令

命令为gcc -m64 -no-pie -fno-PIC hello.c -E -o hello.i 或 cpp hello.c > hello.i

图 2.2.1 预处理命令

2.3 Hello的预处理结果解析

图2.3.1 hello.i开头部分

图2.3.2 hello.i结尾部分

打开hello.i,看到文件试可读的文本文件,共3091行,查看文件头部代码,发现有加载.c文件中include的头文件;查看文件尾部代码,发现与.c文件中的main函数部分相同

2.4 本章小结

本章介绍了预处理的概念和作用,以hello.c程序为例,演示了预处理的命令,并简单地对得到的.i文件进行解析。得到.i文件,是下一步编译的基础。

(第2章0.5分)

第3章 编译 3.1 编译的概念与作用

编译概念:编译是指编译器把预处理之后生成的.i文件翻译成.s文件,其中.s文件里是汇编语言程序

编译作用:编译器会检查代码的语法,看是否有错误。检查无误后将代码转变成汇编语言。在这个过程中还会对代码进行分析,对代码进行多种变换,实现速度和占用空间上的优化(如GCC的O2模式)。

3.2 在Ubuntu下编译的命令

gcc -m64 -no-pie -fno-PIC -S hello.i -o hello.s

图3.2.1 编译命令

3.3 Hello的编译结果解析

1.数据常量

图3.3.1 hello.s立即数记录方式

立即数采用$+对应数字的方式记录

图3.3.2 hello.s字符串记录方式

字符串会被保存在数据段里,.LC0标号代表了对源代码中一个字符串常量的引用

2.数据变量

图3.3.3 hello.s数据变量记录方式

局部变量存在栈上,当用到局部变量时,会通过改变栈指针的指向位置,在堆栈上开辟出一块空间,储存局部变量的值。

3.赋值

图3.3.4 hello.s赋值方式

在循环开始时,将变量i赋值为0

4.算术操作

图3.3.5 hello.s算术操作

每次循环结束对给i加1,对应i++操作

5.关系操作

图3.3.6 hello.s关系操作“

8.   if(*fmt != '%') {

9.   *p++= *fmt;

10. continue;

11. }

12.

13. fmt++;

14.

15. switch (*fmt) {

16. case'x':

17. itoa(tmp, *((int*)p_next_arg));

18. strcpy(p, tmp);

19. p_next_arg += 4;

20. p +=strlen(tmp);

21. break;

22. case's':

23. break;

24. default:

25. break;

26. }

27. }

28.

29. return (p - buf);

30. }

vsprintf函数:作用为格式化,接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化输出,并返回字符串的长度。

接下来到write系统函数。

1.   write:

2.        mov eax, _NR_write

3.        mov ebx, [esp + 4]

4.        mov ecx, [esp + 8]  

5.        int INT_VECTOR_SYS_CALL

这里会给寄存器传递几个参数,以一个int结束,int INT_VECTOR_SYS_CALL表示要通过系统来调用sys_call这个函数。接下来是到陷阱-系统调用 syscall。

1.   sys_call:

2.        call save      

3.        push dword [p_proc_ready]      

4.        sti       

5.        push ecx  //打印出的元素个数

6.        push ebx  //要打印的buf字符数组中的第一个元素

7.        call [sys_call_table + eax * 4]   //不断打印字符,直到遇到’\0’

8.        add esp, 4 * 3

9.       

10.      mov [esi + EAXREG - P_STACKBASE], eax

11.     

12.      cli

13.      ret

当字符显示驱动子程序,从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)后,显示芯片按照显示器的刷新率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量),把画面显示在显示器上。

8.4 getchar的实现分析

查看getchar的源代码:

int getchar(void)

{

    static char buf[BUFSIZ];

    static char* bb=buf;

    static int n=0;

    if(n==0)

    {

        n=read(0,buf,BUFSIZ);

        bb=buf;

}

        return (--n>=0)?(unsigned char)*bb++:EOF;

}

可以看到getchar的底层实现是通过系统函数read实现的。调用getchar时,会等待用户输入,输入回车后,输入的字符会存放在缓冲区中。第一次调用getchar时,需要从键盘输入,但如果输入了多个字符,之后的getchar会直接从缓冲区中读取字符。getchar返回读入的第一个字符,若读入失败(读到EOF)则返回-1。

异步异常-键盘中断的处理:当用户按键时,键盘接口会得到一个代表该按键的键盘扫描码,同时产生一个中断请求。中断请求抢占当前进程运行键盘中断子程序,键盘中断子程序先从键盘接口取得该按键的扫描码并转换成 ASCII 码,保存到系统的键盘缓冲区之中。程序执行完之后键盘缓冲区中的内容会被输入到shell里,这个在之前第六章已经试验过了。

8.5本章小结

本章介绍了linux下I/O设备的管理方法,由于linux一切皆文件的特性,将所有设备映射为文件,用读写的方式控制I/O。允许linux内核引出一个简单、低级的应用接口——Unix I/O,且分析了printf函数和getchar函数这两个基于Unix I/O中的实现函数的封装函数的实现方式。

(第8章1分)

结论

Hello:

1.用c语言编写hello程序,保存为.c文件

2.预处理,主要是处理include(展开用到的外部库)和define,保存为.i文件

3.编译,把.i文件编译成汇编语言,保存成.s文件

4.汇编,把.s文件变为可重定位目标文件,保存为.o

5.链接,把各种代码和数据片段收集并组合成为一个单一文件,得到可执行文件hello

6.运行,在shell中运行可执行文件

7.fork,shell调用fork,创建一个子进程

8.execve,shell调用execve,execve 调用启动加载器,加映射虚拟内存(覆盖之前),进入程序入口后程序开始载入物理内存,然后进入 main 函数。

9.程序的运行过程,如果运行途中键入 ctr-c ctr-z 则调用 shell 的信号处理函数分别停止、挂起,挂起的程序可用fg指令恢复

10.资源回收:shell 父进程回收子进程,内核删除为这个进程创建的所有数据结构。

Hello的一生短暂而辉煌。在用户看来,它只是被一句输入到shell里的命令,短暂地占据了shell,输出几句简单的句子,之后就被shell带走销声匿迹,它的一生无疑是短暂的。但是在每个CS学习者眼里,它的一生精彩而辉煌,它从诞生开始,就被OS和硬件高高举起,一路保驾护航,它走的每一步上都是历代计算机研究者们的严密论证和多次实践的结果,每一步都凝聚着前人的智慧。我喜欢计算机科学,因为它是由人类创造的科学,如果我有个想法,可以很快编写程序去验证,一个人一台电脑,就有可能改变世界。

(结论0分,缺失 -1分,根据内容酌情加分)

附件

hello.i:C预处理器产生的一个ASCII码的中间文件,用于分析预处理过程。

hello.s:C编译器产生的一个ASCII汇编语言文件,用于分析编译的过程。

hello.o:汇编器产生的可重定位目标程序,用于分析汇编的过程。

hello:链接器产生的可执行目标文件,用于分析链接的过程。

hello.txt:hello.o的反汇编文件,用于分析可重定位目标文件hello.o。

hello2.txt:hello的反汇编文件,用于分析可执行目标文件hello。

hello.elf:hello.o的ELF格式,用于分析可重定位目标文件hello.o。

hello2.elf:hello的ELF格式,用于分析可执行目标文件hello

图 附件 各个中间文件

(附件0分,缺失 -1分)

参考文献

为完成本次大作业你翻阅的书籍与网站等

(参考文献0分,缺失 -1分)

[1]  RANDALE.BRYANT, DAVIDR.O‘HALLARON. 深入理解计算机系统[M]. 机械工业出版社, 2011.

[2]  https://www.cnblogs.com/clover-toeic/p/3851102.html

[3]  https://www.runoob.com/linux/linux-comm-pstree.html

[4]  https://www.runoob.com/cprogramming/c-function-vsprintf.html

[5]  https://www.cnblogs.com/pianist/p/3315801.html

[6]   https://www.cnblogs.com/jiqing9006/p/8268233.html

[7]  CMU的csapp课程,bilibili网站提供翻译

【精校中英字幕】2015 CMU 15-213 CSAPP 深入理解计算机系统 课程视频_哔哩哔哩_bilibili

[8]  https://www.cnblogs.com/pianist/p/3315801.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有