(以下内容还未整理好,谨慎观看哈哈哈)
前言知识:
主存储器:是整个存储系统的核心,它用来存放计算机运行期间所需要的程序和数据,CPU可直接随机地对它进行访问。
(主存地读写操作是在控制器地控制下进行的,只有接收到来自控制器地读写命令或写允许后,才能实现正确地读写操作)
CPU:是整个计算机地核心,是对指令流和数据流在时间上与空间上实施正确地控制。
(指令流:指的是CPU执行的指令序列;数据流:指的是根据指令操作要求依次存取数据地序列)
若用计算机来解决某个问题,首先要为这个问题编制解题程序,而程序又是指令的有序集合。
按照“存储程序”的概念,只要把程序装入主存储器后,即可由计算机自动的完成取指令和执行指令的任务。
(程序要执行,必须被CPU调用执行,而前提是程序装入到主存中)
那么,程序如何装入主存储器?
1.程序的装入与链接
大致流程图如下:
具体流程如下:
(1)编译(一般来说高级语言的编译要经过预处理、编译和汇编这几个过程)
用户源程序(比如.c文件)经过编译生成目标模块(.obj 汇编语言或机器语言)
预处理:
预编译过程对源代码做了如下的操作:
删除所有的注释信息
删除所有的 #define 并展开所有宏定义
插入所有 #include 文件注1的内容到源文件中的对应位置,include过程是递归执行的
gcc可以使用如下命令对C语言进行预编译并且把预编译的结果输出到hello.i文件中
gcc -E hello.c -o hello.i
编译:
编译就是对预处理之后的文件进行词法分析、语法分析、语义分析、中间代码生成并优化后生成相应的汇编文件。我们使用如下命令来编译预处理之后的文件
gcc -S hello.i -o hello.s
或者我们也可以把预处理和编译合为一步
gcc -S hello.c -o hello.s
具体讲解一下编译过程:(后续完成)
词法分析:
语法分析:
语义分析:
中间代码生成:
代码优化与目标代码生成:
汇编:
汇编的目的是把汇编代码转化为机器指令,因为几乎每一条汇编指令都对应着一条机器指令,所以汇编的过程相对而言非常的简单。我们可以使用如下命令实现汇编
gcc -c hello.s -o hello.o
或者我们也可以直接把源代码文件编译为目标文件
gcc -c hello.c -o hello.o
汇编操作所生成的文件叫做目标文件(Object File),目标文件的结构与可执行文件是一致的,它们之间只存在着一些细微的差异。目标文件是无法被执行的,它还需要经过链接这一步操作,目标文件被链接之后才可以产生可执行文件。
(2)链接
将编译后形成的多个目标模块以及它们所需要的库函数链接在一起形成装入模块。(装入模块虽然具有统一的地址空间,但是它任是以“0”作为参考地址)
(3)装入
将装入模块装入内存实际物理地址空间,并修改程序中与地址有关的代码。(这一过程叫做地址重定位)。
程序装入内存,操作系统要为新装入内存的作业分配必要的资源,并为它创建进程(申请空白的PCB、初始化进程描述信息、为进程分配资源和存储空间、将进程插入到就绪队列中)
装人内存这一块涉及到操作系统中的存储管理。(把程序装入内存的哪个区域?连续区域还是离散区域?)
一般这里我们会涉及到页式存储管理、段式存储管理、段页式存储管理和虚拟存储管理。
程序装入之后,cpu怎么控制指令的执行呢?
2.CPU对主存的基本操作
CPU对主存进行读写操作时候,首先CPU在地址总线上给出地址信号,然后发出相应的读或写命令,并在数据总线上交换信息。读写的基本操作如下:
那么问题来了,CPU起初的地址信号哪里来的?
(I/O软件将用户编制的程序通过总线(现在一般为单总线结构:CPU、主存和I/O设备都连结到同一组总线上,使得CPU在I/O设备与主存交换信息时仍可继续处理其他任务)输入信息到主机(由CPU和主存构成)中在程序开始执行前,将程序指令序列的起始地址,即程序的第一条指令所在的内存单元地址送入PC,CPU按照 PC的指示从内存读取第一条指令(取指))。
程序在编译的目标代码生成过程中,通过代码生成算法将中间代码转换为特定机器的机器语言。如:
所以,在内存中装载的都是程序的相应指令。
3.CPU调度进程执行程序