锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

程序人生-Hello‘s P2P

时间:2023-08-05 03:07:00 连接器df1ec6431连接器

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-7VhcuysH-1652883577225)(media/6adc987e0270ab8ce90ba4fe6207a880.jpeg)]

计算机系统

大作业

题 目 程序人生-Hello’s P2P

专 业 计算机类

学 号 120L021329

班 级 2003011

学 生 蒋世鑫

指 导 教 师 郑贵滨

计算机科学与技术学院

2022年5月

摘 要

本论文将CSAPP通过课程内容hello小程序的一生,全面梳理和回顾我们所学。以hello.c编译、链接、加载、运行、终止和回收的过程始于原始程序。我们主要在Ubuntu相关操作应合理使用Ubuntu下面的操作工具,结合对计算机系统的深入理解和课堂教师的教学,进行详细的过程分析,目的是连接整个计算机系统系统,加深对计算机系统的理解。

**关键词:**hello;计算机系统;计算机系统结构;程序生命周期;底层原理;

**
**

目 录

第1章 概述

1.1 Hello简介

1.1.1Hello的P2P过程

1.1.2Hello的020过程

1.2 环境与工具

1.2.1硬件

1.2.2软件

1.2.开发和调试工具

1.3 中间结果

1.4 本章小结

第2章 预处理

2.1 预处理的概念和作用

2.1.1概念

2.1.2作用

2.2在Ubuntu下一个预处理命令

2.3 Hello预处理结果分析

2.3.1预处理结果

2.3.2解析

2.4 本章小结

第3章 编译

3.1 概念与作用的编译

3.1.1概念

3.1.2作用:

3.2 在Ubuntu下面编译的命令

3.2.1命令

3.2.2截图

3.3 Hello分析编译结果

3.3.1数据

3.3.2赋值

3.3.3算术操作

3.3.4关系操作

3.3.5数组操作

3.3.7函数操作

3.4 本章小结

第4章 汇编

4.1 汇编的概念和功能

4.1.1概念

4.1.2作用

4.2 在Ubuntu下面汇编的命令

4.2.1命令:

4.2.2截图:

4.3 可重定位目标elf格式

4.3.1 ELF header

4.3.2节头目表

4.4 Hello.o的结果解析

4.4.1反汇编指令及截图

4.4.机器语言的组成

4.4.3与汇编语言的映射关系

4.4.4对照分析

4.5 本章小结

第5章 链接

5.1 链接的概念和功能

5.1.1链接的概念

5.1.2链接的作用

5.2 在Ubuntu下链接命令

5.2.1命令

5.2.2截图

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

5.3.1ELF 头

5.3.2节头目表

5.3.3程序头表

5.4 hello虚拟地址空间

5.5 链接重定位过程分析

5.5.1命令

5.5.2分析

5.6 hello的执行流程

5.7 Hello的动态链接分析

5.8 本章小结

第6章 hello进程管理

6.1 过程的概念和作用

6.1.1概念

6.1.2作用

6.2 简述壳Shell-bash作用及处理过程

6.2.1作用

6.2.2处理流程

6.3 Hello的fork创建过程的过程

6.4 Hello的execve过程

6.5 Hello的进程执行

6.6 hello异常和信号处理

6.6.1正常运行

6.6.2CTRL Z

6.6.3CTRL C

6.6.4回车

6.6.5不断乱按

6.7本章小结

第7章 hello的存储管理

7.1 hello存储地址空间

7.1.1逻辑地址

7.1.2线性地址

7.1.3虚拟地址

7.1.4物理地址

7.2 Intel从逻辑地址到线性地址的转换-段管理

7.2.1含义

7.2.2过程

7.3 Hello从线性地址到物理地址的转换-页面管理

7.3.1概念

7.3.2过程

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

7.4.1基于Intel Core i7

7.4.2过程

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

7.5.1 L1 dCache 参数

7.5.2过程

7.6 hello进程fork时间内存映射

7.7 hello进程execve时间内存映射

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

7.9动态存储分配管理

7.9.1概念

7.9.2方法与策略

7.10本章小结

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

8.1.设备模型化

8.1.2设备管理

8.2 简述Unix IO接口及其函数

8.2.1Unix IO接口

8.2.2Unix IO函数

8.3 printf的实现分析

8.3.1 printf()函数体

8.3.2 vsprintf()

8.3.3 write()

8.4 getchar的实现分析

8.5本章小结

结论

附件

参考文献

第1章 概述

1.1 Hello简介

1.1.1Hello的P2P过程

hello程序的生命周期来自高级C语言程序hello.c文件开始的,因为程序员通过这种形式写程序并能够被其他人读懂。但为了在系统上运行hello.c程序,hello.c文件需要转换为可执行文件。

编译器驱动程序完成了从源文件到目标文件的转换。gcc编译器读取源程序hello.c并在四个阶段完成过四个阶段完成的。

(1)预处理阶段

预处理器(cpp)根据字符#开头的命令,修改原始C程序。在这里,hello.c第1行的#include命令告诉预处理器读取系统头文件stdio.h并将其直接插入程序文本中。获得另一个C程序,通常是.作为文件扩展名。

(2)编译阶段

编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。该程序包含函数main每个句子都以文本格式描述了一个低级机器语言指令。

(3)汇编阶段

汇编器(as)将hello.s将这些指令翻译成机器语言指令,程序(relocatable object program)将结果保存在文件中的格式hello.o中。hello.o文件是二进制文件,包含字节hello指令编码。

(4)链接阶段

链接器(ld)负责把hello.o调用的标准C库函数printf对应的printf.o单独预编目标文件和hello.o程序合并。最终获得可执行的目标文件hello,它需要加载到内存才能执行。

在shell中输入命令./hello后,shell调用fork()产生子过程Process,实现了hello.c从Program到Process的转化。

1.1.2Hello的020过程

Hello的020是指hello.c文件“From 0 to 0”,初始时内存中并无hello文件的相关内容是From ”。通过在Shell下调用execve函数,系统会将hello文件载入内存,执行相关代码,当程序运行结束后, hello进程被回收,并由内核删除hello相关数据,这即为“to 0”。

1.2 环境与工具

列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。

1.2.1硬件

Intel Core i7

2.30 GHz

16.0 GB RAM

512GB HD Disk

1.2.2软件

Windows10 64位;

VirtualBox6.1;

ubuntu20.04;

1.2.3开发与调试工具

gedit,gcc,vim,notepad++,readelf, objdump, hexedit, edb

1.3 中间结果

列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。

文件名 作用
hello.i 预处理后得到的文本文件
hello.s 编译后得到的汇编语言文件
hello.o 汇编后得到的可重定位目标文件
elf.txt 用readelf读取hello.o得到的ELF格式信息
asm.txt 反汇编hello.o得到的反汇编文件
hello.elf 由hello可执行文件生成的.elf文件
hello.asm 反汇编hello可执行文件得到的反汇编文件

1.4 本章小结

本章简要介绍了hello 的P2P,020的具体含义,同时列出了论文研究时采用的具体软硬件环境和中间结果。

(第1章0.5分)

第2章 预处理

2.1 预处理的概念与作用

以下格式自行编排,编辑时删除

2.1.1概念

预处理一般是指在程序源代码被翻译为目标代码的过程中,生成二进制代码之前的过程。典型地,由预处理器(preprocessor) 对程序源代码文本进行处理,得到的结果再由编译器核心进一步编译。这个过程并不对程序的源代码进行解析,但它把源代码分割或处理成为特定的单位——(用C/C++的术语来说是)预处理记号(preprocessing token)用来支持语言特性(如C/C++的宏调用)。

最常见的预处理是在C语言和C++语言中。ISO C和ISO C++都规定程序由源代码被翻译分为若干有序的阶段(phase),通常前几个阶段由预处理器实现。预处理中会展开.c文件中以#起始的行,试图解释为预处理指令(preprocessing directive) 。其中ISO C/C++要求支持的格式包括#if/#ifdef/#ifndef/#else/#elif/#endif(条件编译)、#define(宏定义)、#include(源文件包含)、#line(行控制)、#error(错误指令)、#pragma(和实现相关的杂注)以及单独的#(空指令)。预处理指令一般被用来使源代码在不同的执行环境中被方便的修改或者编译。

以hello.c中的"#include"为例,它会把hello.c这一行的命令告诉预处理器。预处理器会读取系统头文件stdio.h的内容,并把它直接插入程序文本中。得到另一个C程序,通常以.i作为文件扩展名。

2.1.2作用

(1)将源文件中用#include 形式声明的文件复制到新的程序中。比如 hello.c 第 6-8 行中的#include 等命令告诉预处理器读取系统头文件 stdio.h unistd.h stdlib.h 的内容,并把它直接插入到程序文本中。

(2)用实际值替换用#define 定义的字符串

(3)根据#if 后面的条件决定需要编译的代码

(4)特殊符号,预编译程序可以识别一些特殊的符号, 预编译程序对于在源程序中出现的这些串将用合适的值进行替换。

2.2在Ubuntu下预处理的命令

(1)命令: cpp hello.c > hello.i

gcc -E hello.c -o hello.i

(2)截图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b8gMEzAe-1652883577227)(media/261f52aff3aacde1871d7cbd27e960a0.png)]

图 1预处理命令

2.3 Hello的预处理结果解析

2.3.1预处理结果

(1)代码从原代码的23行经预处理后变成了3060行;

(2)原代码main函数体未改变,但三个预处理命令#include、#include、#include和注释被约三千行代码取代;

2.3.2解析

(1)取代预处理命令的三千多行代码是三个头文件stdio.h\unistd.h\stdlib.h的依次展开;

(2)从hello.i程序中可以分析得到具体的展开过程:编译器会首先读取原指令,然后到Ubuntu默认的环境变量中寻找头文件,例如"/usr/include/stdio.h"下找到了头文件stdio.h文件。然后把头文件中的代码复制到原代码中取代原指令;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cT9mWmZI-1652883577227)(media/32ad4c76b1b51b7d9d44c55574b14328.png)]

图 2复制的stdio.h代码

(3)若得到的新代码中使用了#define或#include语句,则会继续按(2)中过程不断展开,递归循环直至武#define语句为止;

(4)查阅相关资料后,得知编译器同时会把条件编译的命令进行解析选择编译代码;同时删除空指令、注释和多余空白字符;替换部分值;

(4)最后得到一个包含大量库函数、编译指令和原代码的文件,此文件已不需要外部库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFn0t9t3-1652883577227)(media/db14241d89e5a980784eccd03d1759a9.png)]

图 3原始代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8HcGngdo-1652883577228)(media/ce77111f7887c2ad5d7008f5363fa575.png)]

图 4预处理后的代码

2.4 本章小结

本章主要介绍了预处理(包括头文件的展开、宏替换、去掉注释、条件编译)的概念和应用功能,以及Ubuntu下预处理的两个指令,同时具体的对我们的hello.c文件的预处理结果hello.i文本文件进行了解析,详细了解了预处理的内涵。

(第2章0.5分)

第3章 编译

3.1 编译的概念与作用

3.1.1概念

编译器通过语法分析和词法分析,在符合语法规则的条件下,将得到的hello.i文件翻译为ASCII汇编语言文件hello.s。这里编译器把hello.i翻译为hello.s,并以文本的形式描述了一条条低级机器语言指令。编译的大概流程为:

(1)语法分析:编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,方法分为两种:自上而下分析法和自下而上分析法;

(2)中间代码:源程序的一种内部表示,或称中间语言。中间代码的作用是可使编译程序的结构在逻辑上更为简单明确,特别是可使目标代码的优化比较容易实现中间代码。

(3)代码优化:指对程序进行多种等价变换,使得从变换后的程序出发,能生成更有效的目标代码。

(4)目标代码:生成是编译的最后一个阶段。目标代码生成器把语法分析后或优化后的中间代码变换成目标代码。此处指汇编语言代码,须经过汇编程序汇编后,成为可执行的机器语言代码。

3.1.2作用:

(1)分析单词符号串是否形成符合语法规则;

(2)使编译程序的结构在逻辑上更为简单明确;

(3)生成更有效的目标代码;

(4)得到汇编代码,经汇编后可得到机器语言代码。

3.2 在Ubuntu下编译的命令

3.2.1命令

gcc -S hello.i -o hello.s

3.2.2截图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-20fdPlNf-1652883577228)(media/7de25fac1ab140eae3a1988897b5b651.png)]

图 5编译命令

3.3 Hello的编译结果解析

3.3.1数据

3.3.1.1常量

(1)整形常量

hello.c中的整形常量包括第13行if语句和17行语句至19行语句里的4、0、8、1、2、3。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqGkh5xX-1652883577229)(media/4a03b4ff16a8bec42cecf37062cccbf8.png)]

图 6原代码

在hello.s中,整形常量被直接表示为"$+N"的形式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZaTM63Kx-1652883577230)(media/b14b261424d5c63b0908816e7af81354.png)]

图 7立即数形式

(2)字符串常量

hello.c中的字符串常量包括第14行语句和第18行语句里的字符串,都作为printf()的参数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Zd4FANQ-1652883577230)(media/add904df5f21edd639eb921babd4b26a.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nP1TjMqE-1652883577230)(media/54660e7af5993271e545f98dab6c2263.png)]

图 8原代码的字符串

这两个字符串常量在汇编代码均储存在.rodata中,表示为

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wEGmLtIe-1652883577231)(media/d74113d8bc0c76a3f58d92ed62dc1930.png)]

图 9编译后的字符串

其中的英文字符和符号不变,而中文字符均用UTF-8编码表示。

3.3.1.2变量

(1)int

hello.c中的int变量包括函数内部定义的int i和传入main的参数int argc。

函数内部的非静态非全局变量都属于局部变量,编译器会把局部变量存储在寄存器或者栈中。编译器每一次对i和argc的调用和赋值操作都会对相应寄存器和栈空间进行操作。在hello.s中,i和argc分别存在%eax和堆栈中。

以下面两个指令为例,分别表示hello.c语句"argc!=4"和"i=0"。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QBFr9W8l-1652883577231)(media/e85fa200f9c6157defa98b3b5a0bdfcd.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzYmrsfJ-1652883577232)(media/4e008433506c913d1a089e593317a83b.png)]

图 10int编译代码

(2)数组

hello.c中的数组变量是传入main的参数char * argv[4]。

在这里编译器在对其进行编译后,把首地址存入栈中。在需要对其相关教学操作时,只需通过寄存器间接寻址的方法访问。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltCDGW6I-1652883577232)(media/13a75abd813ab9b05361e8c94802737b.png)]

图 11数组编译代码

3.3.2赋值

在汇编代码中,对变量的赋值通过mov指令实现,根据数据的大小决定使用哪条指令。

在这里hello.c中只涉及一句赋值操作i=0,编译器利用movl实现。

3.3.3算术操作

hello.c第17行的int变量i的算术操作i++,被编译器翻译为对栈上存储值加一的形式。通过addl指令,实现栈上对应地址存储值的加一操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-td9AN2CX-1652883577232)(media/30d5e60f99406a15026acb168e24ebba.png)]

图 12原代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-APu5WyM8-1652883577233)(media/d35411b2090e283c3c061b96869c622f.png)]

图 13汇编代码

3.3.4关系操作

在汇编语言中,关系操作会利用cmp比较指令和test测试指令实现,同时会设置条件码。

(1)argc!=4

在hello.c中第13行的argc!=4,在hello.s中被编译器翻译为:把存储在对应地址的argc值与4比较,并根据结果设置条件码;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gb1qBQkZ-1652883577233)(media/f31ea92daff8417c9868656c155f8a90.png)]

图 14汇编代码

(2)i<8

在hello.c第17行的i<8,在hello.s中被编译器翻译为:把存储在对应地址的i的值与8比较,根据结果设置条件码;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YzyimLw1-1652883577233)(media/6d6b17085d1e02fbabb5050e9333a84e.png)]

图 15汇编代码

3.3.5数组操作

在汇编语言中,对数组的操作主要是通过寄存器间接寻址实现的。

在hello.c第18~19行,对字符串指针数组char *argv[]进行了取值操作。翻译时,编译器首先会利用指令move取出argv[]数组基址的值。因为数组是连续存储的,编译器根据数组元素字节的大小,利用指令addl在基址值上加上对应索引的字节的倍数,得到argv[1]、argv[2]和argv[3]的值。char*数据类型大小为八个字节,则只需加8的倍数即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ForML04q-1652883577234)(media/8a1aca782452ac98898832f933c15494.png)]

图 16汇编代码

3.3.6控制转移

汇编语言中,控制转移通过比较指令cmp和跳转指令j*或条件传送指令实现。

  1. if(argc!=4)

这里由argc!=4关系操作设置的条件码决定je是否跳转。如果argc不等于4则执行if函数体内的操作对应的汇编代码;如果等于4,则跳转至L2.,不执行if函数体内的汇编指令。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ymsiPWBF-1652883577234)(media/9d92ee7264913498d2fc3885cd29bc49.png)]

图 17汇编代码

  1. for(i=0;i<8;i++)

这里由i<8关系操作设置的条件码决定jle是否跳转,如果i小于8则执行循环体内的操作(在.L4);如果大于等于8则不跳转,结束循环继续外部操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NqhohZ0Y-1652883577234)(media/aabed71b929665178827301b78feeef4.png)]

图 18汇编代码

再由条件码决定je(je用于判断cmpl产生的条件码,若两个操作数的值不相等则跳转到指定地址)的跳转。

3.3.7函数操作

C语言中,调用函数时进行的操作如下:

(1)传递控制:

进行过程 Q 的时候,程序计数器必须设置为 Q 的代码的起始地址,然后在返回时,要把程序计数器设置为 P 中调用 Q 后面那条指令的地址。

(2)传递数据:

P 必须能够向 Q 提供一个或多个参数,Q 必须能够向 P 中返回一个值。参数可以地址也可以为值。默认传参的顺序是%rdi>%rsi>%rdx>%rcx>%r8>%r9>栈。而默认返回的值存在%eax中。

(3)分配和释放内存:

在开始时,Q 可能需要为局部变量分配空间,而在返回前,又必须释放这些空间。

  1. main()函数
  2. 参数传递和返回:传入参数argc和argv[],存在%ecx寄存器和;
  3. 函数调用:被shell利用指令call进行函数调用,用栈保存调用位置的下一条指令;
  4. 函数返回:设置%eax为0并利用ret指令返回或直接调用exit()退出。
  5. 对应汇编代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CBz1tGg2-1652883577235)(media/1bcbcc5f0f1d98191e03e9f237b1623b.png)]

图 19main对应汇编代码

  1. printf()函数

(1)参数传递和返回:第一次不传入参数,第二次传入argv[1]和argv[2]的值并保存在寄存器中;

(2)函数调用:被main()利用指令call puts或者call printf和相对寻址调用,并用栈保存调用位置的下一条指令;

(3)函数返回:利用ret指令返回;

(4)对应汇编编码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HcYTlvbs-1652883577235)(media/606deaee2cf5d69b38e72c43eb7079f1.png)]

图 20printf对应汇编代码1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qA9YsbIb-1652883577235)(media/a8f05bef0976f6110ed1f6ad23007b4b.png)]

图 21printf对应汇编代码2

3.exit()

(1)参数传递和返回:传入整形常量1;

(2)函数调用:在main()内的if函数体内当满足if条件时被main()利用指令call和相对寻址调用,并用栈保存调用位置的下一条指令;

(3)对应汇编代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4FUEm2ar-1652883577235)(media/3abd195afebbdaa4e3e39bb8e4c3a08e.png)]

图 22exit对应汇编代码

4.atoi()

(1)参数传递和返回:传入argv[3],并把值保存在栈或寄存器中。返回一个整形常量保存在%eax中;

(2)函数调用:在main()函数内利用call指令和相对寻址调用,并用栈保存调用位置的下一条指令;

(3)对应汇编代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unbN1LXX-1652883577236)(media/563647c9ddc69d378b4d53f3925db979.png)]

图 23atoi对应汇编代码

5.sleep()

(1)参数传递与返回:传入atoi()的返回值—1个整形变量,并将其保存在栈或寄存器中;

(2)函数调用:在main()函数内利用call指令和相对寻址调用,并用栈保存调用位置的下一条指令;

(3)对应汇编代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0qY5qS3-1652883577236)(media/6d052b508afa203dc86ac30481eff6cf.png)]

图 24sleep对应汇编代码

6.getchar()

(1)函数调用:在main()函数内利用call指令和相对寻址调用,并用栈保存调用位置的下一条指令;

(2)对应汇编代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dw0xc65I-1652883577236)(media/1d9fbc56e6028224d091005baa63aab4.png)]

图 25getchar对应汇编代码

3.4 本章小结

本章主要介绍了编译的概念以及过程,编译是将文本文件翻译成汇编语言程序,为后续将其转化为二进制机器码做准备的过程。而编译器所做的工作,就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码表示。

同时通过示例函数表现了.c文件中的代码如何转换成为对应汇编指令。另外还以此例详细介绍了汇编代码如何实现变量、常量、传递参数以及分支和循环等工作。

通过本章的分析我更深刻地理解了C语言的数据与操作,对C语言翻译成汇编语言有了更好的掌握。因为汇编语言的通用性,这也相当于掌握了语言间的一些共性。

(第3章2分)

第4章 汇编

4.1 汇编的概念与作用

4.1.1概念

汇编器将hello.s翻译为二进制的机器语言指令,把这些指令打包成一种叫做可重定向目标程序的格式,并把结果保存在目标文件hello.o中。这个过程叫做汇编。

4.1.2作用

把汇编语言指令转化为机器可直接识别执行的二进制代码机器语言形式,使得代码可以真正地被机器理解与执行。

4.2 在Ubuntu下汇编的命令

4.2.1命令:

gcc -m64 -no-pie-fno-PIC -c hello.s -o hello.o

4.2.2截图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nsj2mgQg-1652883577237)(media/3899166e439f079ef3805f4639ed80db.png)]

图 26汇编指令

4.3 可重定位目标elf格式

利用readelf -all hello.o > elf.txt得到可重定向目标程序的elf格式。

4.3.1 ELF header

ELF头以一个16字节的序列Magic开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。另外ELF头的信息还包括ELF头的大小、目标文件的类型(可重定位、可执行目标还是共享目标)、机器类型(如x86-64)、节头部表的文件偏移,以及节头部表中条目的大小和数量。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3xrkrQd-1652883577237)(media/3617ce2530c353f6262dab67e77d1be1.png)]

图 27ELF HEADER

4.3.2节头目表

描述了不同节的位置、大小及类型,其中目标文件的每个节都有一个固定大小的条目(entry)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2tLDRhcF-1652883577237)(media/970788e3912567da59c37c406791b192.png)]

图 28节头表

其中不同flags对应的意义:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T8NP2oCr-1652883577237)(media/d76a6e948c9ec1c3cddf13365452efe7.png)]

图 29标志含义

4.3.3重定位节’.rela.text’

一个.text节中位置的列表,表述了各个段引用的外部符号等,在链接时,需要通过重定位节对这些位置的地址进行修改。链接器会通过重定位条目的类型判断该使用哪种方法计算正确的地址值,通过偏移量等信息计算出正确的地址。

在这里的重定位声明的量有:.rodata中的模式串,puts,exit,printf,slepsecs,sleep,getchar函数。

每一个列代表的信息为:

偏移量—需要进行重定向的代码在.text或.data节中的偏移位置;

信息—包括symbol和type两部分,其中symbol占前半部分,type占后半部分,symbol代表重定位到的目标在.symtab中的偏移量,type代表重定位的类型;

类型—重定位到的目标的类型;

加数—计算重定位位置的辅助信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7cL3guj-1652883577238)(media/c0ad53873a70151db1a66bfa6431f9ca.png)]

图 30.rela.text

4.3.4重定位节’.rela.eh_frame’

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDBU8ePY-1652883577238)(media/4442ee05aa876e1c9dee80b7ec978a56.png)]

图 31.rela.eh_frame

4.3.5符号表

符号表中保存着定位、重定位程序中符号定义和引用的信息,程序中定义和引用的函数和全局变量的信息。所有重定位需要引用的符号都在其中声明。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOToGNVZ-1652883577238)(media/e81d7e34ee830e087a9bec9dc5509c22.png)]

图 32符号表

4.4 Hello.o的结果解析

4.4.1反汇编指令及截图

Objdump -d -r hello.o > asm.txt

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qfr5zUcG-1652883577239)(media/ee4a2d07cd1b64df1ca6dbcd6bf8ee40.png)]

图 33反汇编指令

4.4.2机器语言的构成

机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。一条指令就是机器语言的一个语句,它是一组有意义的二进制代码,指令的基本格式如,操作码字段和地址码字段,其中操作码指明了指令的操作性质及功能,地址码则给出了操作数或操作数的地址。

4.4.3与汇编语言的映射关系

汇编指令是机器指令便于记忆的书写格式。每行的操作码都与其后的汇编指令一一对应。

4.4.4对照分析

(1)操作数

反汇编代码中的立即数都表示为十六进制的数,而hello.s文件中的数都是十进制的;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YGLzfvgd-1652883577239)(media/981ebc7bfc2350c905b7010462e078b4.png)]

图 34操作数

(2)分支转移

在hello.s中,跳转指令的目标地址直接记为.L2,.L3等段名。而在反汇编代码中,跳转的目标为具体的地址,在机器代码中体现为相对偏移地址值,即间接地址寻值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wbxJs6YL-1652883577239)(media/2b324dcdc4f38979ff457e924e5e9fc0.png)]

图 35分支转移

(3)函数调用

在hello.s文件中,call之后直接跟着函数名称,而在反汇编代码中,call 的目标地址是当前指令的下一条指令并会在下一行有提示信息。

这是当调用的函数为共享库中的函数时,需要通过动态链接器作用才能确定函数的运行时执行地址。因此在汇编成为机器语言的时候,对于这些不确定地址的函数调用,将其 call 指令后的相对地址全设置为0,并在.rela.text 节中为其添加重定位条目,等待下一步静态链接的确定相对地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qadMNGSx-1652883577240)(media/6ffff4a23f413ff3ba54c719729d80e1.png)]

图 36函数调用

(4)全局变量访问

在hello.s 文件中,使用段名称+%rip访问 .rodata中的模式串,而在反汇编得到的asm.txt中,使用 0+%rip进行访问。其原因与函数调用类似,rodata 中数据地址在运行时才能确定,故访问时也需要重定位。在汇编成为机器语言时,将操作数设置为全 0 并添加相应的重定位条目。

4.5 本章小结

本章介绍了汇编的概念、作用和结果的分析。在Linux系统下,通过汇编器将汇编语言文件转化为可重定位目标文件。并利用readelf指令得到可重定位文件的ELF格式文件,对该文件进行了详细分析。更重点对可重定位目标文件的反汇编代码与直接得到的汇编代码进行了对比分析。深刻地理解了汇编语言到机器语言实现地转变过程,和这其中为下一步链接做出的准备。

(第4章1分)

第5章 链接

5.1 链接的概念与作用

5.1.1链接的概念

链接是把各种代码和数据片段收集并组合为一个单一文件的过程。这个文件可被加载(复制)到内存并执行。链接可以执行于编译时,也就是在源代码被翻译成机器代码时;也可以执行于加载时,也就是在程序被加载器加载到内存并执行时;甚至执行于运行时,也就是由应用程序来执行。在早期的计算机系统中,链接是手动执行的。在早期的计算机系统中,链接时手动执行的。在现代系统中,链接是由叫做链接器的程序自动执行的。链接器分为编译时使用的动态链接器和加载时和运行时使用的动态链接器。

5.1.2链接的作用

链接使得分离编译成为可能。我们可以把一个大型的应用程序分解为更小、更好管理的模块。我们可以独立地修改和编译这些模块。当我们改变其中的一个模块时,只需简单地重新编译它,并重新链接应用,而不必重新编译其他文件。

从而极大地简化了编写代码的难度,并提高了容错性。

5.2 在Ubuntu下链接的命令

5.2.1命令

ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o ./hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o

5.2.2截图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-638G6wFZ-1652883577240)(media/3e06b1227e11e6c3ecfa1188b4fe555f.png)]

图 37链接指令

使用ld的链接命令,应截图,展示汇编过程! 注意不只连接hello.o文件

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

分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。

输入命令readelf -a hello > hello.elf,区别于Chapter 4 里面的elf.txt文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGwb7eXW-1652883577240)(media/f570460678750a287ae9d097694da9a2.png)]

图 38readelf指令

5.3.1ELF 头

hello的ELF头与elf.txt的信息基本相同。以一个16字节的序列Magic开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。另外ELF头的信息还包括ELF头的大小、目标文件的类型(可重定位、可执行目标还是共享目标)、机器类型(如x86-64)、节头部表的文件偏移,以及节头部表中条目的大小和数量。

但相比未链接前的可重定位目标文件的ELF格式,类型改变为可执行文件,程序头大小和节头数量均增加,而且获得了入口点地址。

5.3.2节头目表

与未链接前的可重定位目标文件的ELF格式相比,每个节的语义未改变,但节的数量增多了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0rO3ZQg-1652883577240)(media/98823b44799c7118e75e68825a527768.png)]

图 39节头目表

5.3.3程序头表

链接后,ELF格式的可执行目标文件多了一个程序头表。这是一个结构数组,描述了系统准备执行所需的段和其他信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KH034tBF-1652883577241)(media/b987035719d36722074e7009330ce695.png)]

图 40程序头表

5.3.4段节表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N8W2o8Pv-1652883577241)(media/ac62c28936793ea297667e5795b47754.png)]

图 41段节头表

5.3.5Dynamic section

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gjjPo1fs-1652883577241)(media/9cd0fa2cddc9bfd337bb633b91ed936d.png)]

图 42Dynamic section

5.3.6重定位节

与可重定向目标文件的几乎相同,但增多了条目。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmSLvEnY-1652883577242)(media/c5754792e744908c19fe26973464b642.png)]

图 43重定位节表

5.3.7符号表

与可重定向目标文件相比,多了.dynsym符号(也就是动态链接的符号),同时原.symtab的条目也增多了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2yVQxeh-1652883577242)(media/752acd073d0def29d609af93bc49da6a.png)]

图 44符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qnHmcM1V-1652883577242)(media/33937a578f81886162d9d87c2258ddda.png)]

图 45符号表2

5.4 hello的虚拟地址空间

根据计算机系统的特性,程序被载入至地址0x400000~0x401000中。在该地址范围内,每个节的地址都与前一节中节对应的 Address 相同。根据edb查看的结果,在地址空间0x400000~0x400fff中存放着与地址空间0x400000~0x401000相同的程序,在0x400fff之后存放的是.dynamic到.shstrtab节的内容。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qjEDFXjT-1652883577242)(media/7ed9f8bde5c8d3ed525e1934c42b657b.png)]

图 46Data Dump

5.5 链接的重定位过程分析

5.5.1命令

Objdump -d -r hello > hello.asm

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AlAJokXX-1652883577243)(media/3d9d05dab5426229644681aaa6f39b68.png)]

图 47反汇编指令

5.5.2分析

(1)链接增加新函数

链接后增加了调用的库函数的代码。在这里我们可以看到链接后的文件中新加入了调用的exit\printf\sleep\atoi\getchar等函数的代码。都是动态链接器将用到的共享库函数加入到了可执行目标文件中。

(2)增加的节

链接后的可执行目标文件增加了.init\.plt\.finl节。其中.init节包含进程初始化时要执行的程序指令,.plt节包含函数连接表,.fiinl节包含进程终止时要执行的程序指令。

(3)函数调用

在链接过程中,链接器解析了重定位条目,call之后的字节代码被链接器直接修改为目标地址与下一条指令的地址之差,指向相应的代码段,从而得到完整的反汇编代码。

(4)跳转

跳转指令参数发生变化。在链接过程中,链接器解析了重定位条目,并计算相对距离,修改了对应位置的字节代码为PLT 中相应函数与下条指令的相对地址,从而得到完整的反汇编代码。

5.5.3链接过程

(1)空间与地址分配

扫描所有的输入目标文件,获得它们的各个段的长度、属性和位置,并且将这些输入目标文件中的符号表中所有的符号定义和符号引用收集起来,统一放到一个全局符号表。再将它们合并。

(2)符号解析与重定位

使用上一步收集到的所有信息,读取输入目标文件中段的数据、重定位信息,并且进行符号解析与重定位、调整代码中的地址等。

5.6 hello的执行流程

0x401000 <_init>

0x401020 <.plt>

0x401030

0x401040

0x401050

0x401060

0x401070

0x401080

0x4010f0 <_start>

0x401120 <_dl_relocate_static_pie>

0x401125

0x4011c0 <__libc_csu_init>

0x401230 <__libc_csu_fini>

0x401238 <_fini>

5.7 Hello的动态链接分析

编译器没有办法预测函数的运行时地址,所以需要添加重定位记录,等待动态链接器处理,为避免运行时修改调用模块的代码段,链接器采用延迟绑定的策略。动态链接器使用过程链接表PLT+全局偏移量表GOT实现函数的动态链接,在GOT中存放函数目标地址,PLT使用GOT中地址跳转到目标函数,在加载时,动态链接器会重定位GOT中的每个条目,使得它包含目标的正确的绝对地址。而.got与.plt节保存着全局偏移量表GOT,其内容从地址0x401000开始。通过edb查看,在dl_init调用前后发生变化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SS62j4c4-1652883577243)(media/f693b0dfd33da07d9ba9d402a48e16e9.png)]

图 48原.got和.plt

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gv1svFxN-1652883577243)(media/1844d2a61834707e7a1c323b308d14a6.png)]

图 49调用后

对于变量而言,我们利用代码段和数据段的相对位置不变的原则计算正确地址。对于库函数而言,需要plt、got合作,plt初始存的是一批代码,它们跳转到got所指示的位置,然后调用链接器。初始时got里面存的都是plt的第二条指令,随后链接器修改got,下一次再调用plt时,指向的就是正确的内存地址。plt就能跳转到正确的区域。

5.8 本章小结

本章中介绍了链接的概念与作用。通过查看hello的虚拟地址空间,并且对比hello与hello.o的反汇编代码,更好地掌握了链接与之中重定位的过程。不过,链接远不止本章所涉及的这么简单,就像是hello会在它运行时要求动态链接器加载和链接某个共享库,而无需在编译时将那些库链接到应用中。

(第5章1分)

第6章 hello进程管理

6.1 进程的概念与作用

6.1.1概念

进程的经典定义就是一个执行中程序的实例。

6.1.2作用

每次运行程序时,shell创建一新进程,在这个进程的上下文切换中运行这个可执行目标文件。应用程序也能够创建新进程,并且在新进程的上下文中运行它们自己的代码或其他应用程序。

进程提供给应用程序的关键抽象:一个独立的逻辑控制流,如同程序独占处理器;一个私有的地址空间,如同程序独占内存系统。

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

6.2.1作用

Shell-bash是一个用C语言编写的交互型应用程序,代表用户运行其他程序。Shell 应用程序提供了一个界面,用户可以通过这个界面进行系统的基本操作,访问操作系统内核的服务。它可以调用其他程序,并且获取其处理结果、在多个程序之间传递参数同时也能被其他程序调用。

6.2.2处理流程

  1. 读入键盘输入的命令;
  2. 判断命令是否正确,且将命令行的参数改造为系统调用execve()内部处理所要求的形式;
  3. 终端进程调用fork()来创建子进程,终端进程调用wait()来等待子进程完成;
  4. 当子进程运行时,它调用execve()根据命令字符串所指定的文件到目录中查找可执行目标文件,调入内存并执行这个程序;
  5. 如果命令行末尾有后台命令符号&则终端进程不执行等待系统调用,并立即在屏幕上打印提示符,让用户输入下一条指令;如果末尾没有&则终端进程一致等待子进程的完成。子进程完成且被处理后,向父进程报告,此时终端进程被唤醒,做完必要的判别工作后,再发提示符,让用户输入新命令。

6.3 Hello的fork进程创建过程

打开Shell,输入命令./hello 120L021329 蒋世鑫,带参数地执行生成的可执行文件。

首先,shell带参执行当前目录下的可执行文件hello,shell会通过fork函数创建一个新的运行的子进程hello。子进程获取了与父进程的上下文,包括栈、通用寄存器、程序计数器,环境变量和打开的文件相同的一份副本。子进程与父进程的最大区别是有着跟父进程不一样的PID,子进程可以读取父进程打开的任何文件。当子进程运行结束时,父进程如果仍然存在,则执行对子进程的回收,否则就由init进程回收子进程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O7ftk2g9-1652883577244)(media/1eb1f35c40c6bced3293d8cffb486ef6.png)]

图 50fork进程

6.4 Hello的execve过程

调用函数fork创建新的子进程之后,子进程会调用execve函数,在当前进程的上下文中加载并运行一个新程序hello。传入参数列表argv和环境变量列表envp。在当前进程的上下文中加载并运行一新的程序。execve 函数从不返回,只有当出现错误时,execve才会返回到调用程序。

(1)在execve加载了Hello之后,它会调用启动代码。而启动代码设置栈,并将控制传递给新程序的主函数main,之后将删除当前进程的代码和地址空间内的内容并将其初始化,然后通过跳转到程序的第一条指令或入口点来运行hello;

(2)将私有的区域映射进来,包括新程序的代码、数据、bss 和栈区域创建新的区域结构。所有这些新的区域都是私有的、写时复制的。代码和数据区域被映射为 hello 文件中的.text 和.data 区;

(3)然后将公共的区域映射进来,比如hello程序与标准C库libc.so链接,这些对象都是动态链接到hello的,然后在用户虚拟地址空间中的共享区域内;

(4)设置程序计数器(PC)。后面加载器跳转到程序的入口点,即设置PC指向_start 地址。_start函数最终调用hello中的 main 函数。下一次调度这个进程时,它将从这个入口点开始执行。Linux 将根据需要换入代码和数据页面。_start 函数调用系统启动该函数__libc_start_main。它初始化执行环境,调用用户层的 main 函数,处理 main 函数的返回值,并且在需要的时候把控制返回到内核。

这样,便完成了在子进程中的加载。

6.5 Hello的进程执行

  1. 在程序运行时,Shell为hello创建了一个子进程,这个子进程与Shell有独立的逻辑控制流,轮流使用处理器,在宏观上看来就像是在平行运行;
  2. 在hello的运行过程中,若hello进程不被抢占,则正常执行;若被抢占,则进入内核模式,进行上下文切换,转入用户模式,调度其他进程;
  3. 直到当hello调用系统函数sleep时,为了最大化利用处理器资源,sleep函数会向内核请求将hello挂起,并进行上下文切换,进入内核模式切换到其他进程,切换回用户模式运行抢占的进程;
  4. 与此同时,将 hello 进程从运行队列加入等待队列,由用户模式变成内核模式,并开始计时;
  5. 当计时结束时,sleep函数返回,发送中断信号,使得hello进程重新被调度。将其从等待队列中移出,转为用户模式。此时 hello 进程就可以继续执行指令。

6.6 hello的异常与信号处理

6.6.1正常运行

进程hello在连续打印八次提示信息后,getchar()会等输入一个字符后结束进程,之后进程将被回收。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HCZAU7if-1652883577244)(media/f5551a3eca4c3c439e64a3a049dfee79.png)]

图 51正常运行

6.6.2CTRL+Z

(1)异常及信号:

陷阱异常,内核产生并向Shell进程发送SIGSTP信号。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hukU7Yg8-1652883577244)(media/3e004c546a16a55f8b43bdee5abb1aee.png)]

图 52程序停止

(2)处理:

Shell会转发SIGTSTP 信号到前台进程组中的每个进程,挂起前台作业,即挂起进程 hello。

(3)命令执行与截图:

由ps和jobs命令查看进程,可发现hello进程被挂起而未被回收。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3C6AXWZU-1652883577244)(media/b1754a614e101620a6f795408cc873ca.png)]

图 53进程信息

pstree可查看进程的分层情况,以树状图的形式显示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y0EUCcJQ-1652883577245)(media/bd13ab74f79a8e11b4c535f7899f43d5.png)]

图 54进程树

可利用kill终止或杀死指定的进程,如hello。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8CSuCpMe-1652883577245)(media/2952a7623e9d58560c86b58dd941791a.png)]

图 55kill停止

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PNiJAFkK-1652883577245)(media/4eb575936e114566bee8ffa32d01ee81.png)]

图 56kill杀死进程

停止的hello进程可用fg指令转至前台运行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKaZEiqq-1652883577245)(media/cafea014de22421bfc63f61cfe0910c7.png)]

图 57前台运行

6.6.3CTRL+C

(1)异常及信号:

陷阱异常,内核产生并向Shell进程发送SIGINT信号。

(2)处理:

Shell会转发SIGINT 信号到前台进程组中的每个进程, 结束并回收前台进程hello。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnqyOu0p-1652883577246)(media/7e5483e148f44a063faddd18e5badb6e.png)]

图 58hello终止

6.6.4回车

在程序运行中打印回车,shell会将把回车符缓存到stdin中,除最后一个回车被getchar()使用,其他的回车都会等到hello进程结束打印出来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fstwEsMD-1652883577246)(media/a1dfbb07c4616a7e251d2e7c1336aad5.png)]

图 59多次按回车

6.6.5不断乱按

在程序执行过程中处上述动作外其他乱按所造成的输入均缓存到stdin,当getchar的时候读出一个’\n’结尾的字串,自动结束并回收hello进程。之后stdin中的其他字串会当做Shell的命令行输入打印到屏幕上。

6.7本章小结

以下格式自行编排,编辑时删除

本章了解了进程管理的概念与作用。并以hello progress的例子分析研究了fork,execve函数的原理与执行过程,并给出了hello带参执行情况下各种异常与信号处理的结果。使我们熟悉了各种指令、信号的作用以及进程管理的大致流程。

(第6章1分)

第7章 hello的存储管理

7.1 hello的存储器地址空间

7.1.1逻辑地址

逻辑地址(Logical Address)是指由程序产生的与段相关的偏移地址部分,逻辑地址由选择符和偏移量两部分组成。具体而言,是指由程序hello产生的与段相关的偏移地址部分。

7.1.2线性地址

线性地址(Linear Address)是逻辑地址到物理地址变换之间的中间层。逻辑地址经过段机制转化后为线性地址,其为处理器可寻址空间的地址,用于描述程序的分页信息。具体以hello而言,线性地址标志着 hello 应在内存上哪些具体数据块上运行。

7.1.3虚拟地址

有时我们也把逻辑地址称为虚拟地址。因为与虚拟内存空间的概念类似,逻辑地址也是与实际物理内存容量无关的,是hello中的虚拟地址。即hello的虚拟地址即为上述逻辑地址和线性地址。

7.1.4物理地址

物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。CPU通过地址总线的寻址,找到真实的物理内存对应地址。如果启用了分页机制,那么hello的线性地址会使用页目录和页表中的项变换成hello的物理地址;如果没有启用分页机制,那么hello的线性地址就直接成为物理地址了。

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

7.2.1含义

Intel处理器从逻辑地址到线性地址的变换通过段式管理的方式实现。每个程序在系统中都保存着一个段表,段表保存着该程序各段装入主存的状况信息,包括段号或者段名、段起点、装入位、段的长度、主存占用区域表、主存可用区域表等,从而方便进行段式管理。

在段寄存器中,存放着段选择符,可以通过段选择符来得到对应段首地址。段选择符存放在段寄存器(16 位)。前 13 位是索引号,后面 3 位包含一些硬件细节。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wPI1nRM4-1652883577246)(media/bc6c8948db7a2ed1378001f40915a7d2.png)]

图 60段寄存器

其中,索引表示用来确定当前使用的段描述符在描述符表中的位置;TI表示根据TI的值判断选择全局描述符表(TI=0,GDT)或选择局部描述符表(TI=1,LDT);RPL表示判断重要等级。RPL=00,为第0级,位于最高级的内核,RPL=11,为第3级,位于最低级的用户状态。

7.2.2过程

给定一个完整的 48 位逻辑地址。

1、首先看段选择符。若T1是0要转换 GDT 中的段,是1转换 LDT中的段,再根据相应寄存器,得到其地址和大小;

2. 拿出段选择符中前13位,查找到对应段描述符,得到32位段基地址;

3、把32位段基地址和32位段内偏移量

相关文章