计算机系统基础一

发布时间 2024-01-12 17:27:37作者: 非衣居士

计算机系统基本组成与功能

1946年2月,第一台通用电子计算机ENIACE(lectronic Nurerical Integrator And Corputer电子数字积分计算机)诞生,使用十进制,采用手动编程,通过设置开关和插拔电缆来实现

1945年冯●诺伊曼发表全新的存储程序通用电子计算机方案

冯●诺伊曼结构最重要的思想是存储程序Stored-program,即把程序存储在计算机内由计算机自动存取指令并执行

内部以二进制表示指令和数据,每条指令由操作码和地址码两部分组成。操作码指出操作类型,地址码指出操作数的地址,由一串指令组成程序

冯 ● 诺依曼型计算机基本工作方式:

  1. 控制器将计算所需的原始数据和计算步骤的程序指令,通过输入设备送入计算机存储器
  2. 控制器向存储器发送取指指令(主要功能是从存储器中读取出指令),存储器中的程序指令送入控制器
  3. 控制器对取出的指令进行译码,然后向存储器发送取数指令,存储器的相关运算数据送入运算器
  4. 控制器向运算器发送运算指令,运算器执行计算得到结果,并把运算结果存入存储器中
  5. 最后控制器向输出设备发送输出指令,输出设备输出计算机结果

​ 现代计算机结构模型

img

  • CPU:中央处理器
  • PC:程序计数器
  • MAR:存储器地址寄存器
  • ALU:算术逻辑部件
  • IR:指令寄存器
  • MDR:存储器数据寄存器
  • GPRs:通用寄存器组(由若干通用寄存器组成,早期就是累加器)

详细工作步骤

  1. 指令获取:当CPU需要执行新的指令时,它会从主存储器(Main Memory)中获取指令。这一过程由内存地址寄存器(MAR)和内存地址控制器(Memory Address Controller)协同完成。MAR存储即将从主存中读取或写入的单元的地址,而内存地址控制器则负责管理数据在主存中的流动
  2. PC更新:程序计数器(PC)会更新,指向下一条要执行的指令的地址。PC是CPU中的一个寄存器,用于存储当前执行的指令的地址
  3. 指令解码:指令被送入指令寄存器(IR)进行解码。指令寄存器是一个暂存器,用于存储从主存中读取的指令。指令译码器(Instruction Decoder)对指令进行解码,以确定需要执行的操作和操作数
  4. 执行指令:一旦指令被成功解码,算术逻辑单元(ALU)开始工作。ALU是CPU的核心部分,负责执行算术和逻辑运算。根据解码的指令,ALU可能从主存中读取数据,进行计算,然后将结果写回主存
  5. 数据流动:在执行指令的过程中,数据在各部件之间流动。数据从主存流入ALU进行计算,然后再流回主存进行存储或进一步的处理。输入设备(如键盘、鼠标)提供原始数据,而输出设备(如显示器、打印机)则显示或输出处理后的数据
  6. 数据存储:当需要存储数据时,数据会从ALU或其他部件流入存储器数据寄存器(MDR),然后被写入主存或某个特定的存储器位置
  7. 通用寄存器组:通用寄存器组(GPRs)由若干通用寄存器组成,早期就是累加器。这些寄存器用于暂存数据和地址,以便快速访问。CPU可以在这些寄存器之间移动数据,进行计算,或与主存进行交互
  8. 控制流:中央处理器(CPU)的控制器负责协调以上所有步骤。控制器通过读取指令并在ALU上执行相应的操作来控制数据流和计算过程

计算机的指令和数据

程序启动前,指令和数据都存放在存储器中,形式上没有差别, 都是01序列

程序由指令组成,程序被启动后,计算机能自动取出一条一条 指令执行,在执行过程中无需人的干预

指令执行过程中,指令和数据被从存储器取到CPU,存放在CPU 内的寄存器中,指令在IR中,数据在GPR中

指令中需给出的信息

  • 操作性质(操作码)

  • 源操作数1 或/和 源操作数2 (立即数、寄存器编号、存储地址)

    • 立即数:指在指令中直接给出的操作数

    • 寄存器编号:计算机中的寄存器用于存储数据和指令,每个寄存器都有一个唯一的编号

    • 存储地址:存储器中的每个单元都有一个唯一的地址,通过该地址可以访问存储器中的数据

  • 目的操作数地址 (寄存器编号、存储地址)

计算机的基本部件及功能

  • 运算器(数据运算):ALU、GPRs、标志寄存器等
  • 存储器(数据存储):存储阵列、地址译码器、读写控制电路
  • 总线(数据传送):数据(MDR)、地址(MAR)和控制线
  • 控制器(控制):对指令译码生成控制信号

什么是计算机:
计算机是一种能对数字化信息进行自动、高速算术和逻辑运算的处理装置

程序开发和执行

  • 高级语言中一条语句对应几条、几十条甚至几百条指令
  • 有面向过程和面向对象的语言之分
  • 处理逻辑分为三种结构 : 顺序结构、选择结构、循环结构

编译程序(Complien):将高级语言源程序转换为机器级目标程序,执行时只要启动目标程序即可

解释程序(nterpreter):将高级语言语句逐条翻译成机器指令并立即执行,不生成目标文件

计算机只能理解机器语言01,最终还是会将高级语言转换为机器语言程序

处理过程

数据经常在各存储部件间传送。故现代计算机大多采用缓存技术

所有过程都是在CPU执行指令所产生的控制信号的作用下进行的

不同层次语言之间的等价转换

不同层次语言之间的等价转换

高级语言开发需要复杂的支持环境

高级语言开发需要复杂的支持环境

程序执行结果不仅取决于算法、程序编写,而且取决于语言处理系统、操作系统、ISA指令集体系结构

ISA处于软件和硬件的交界面(接口),ISA是对硬件的抽象,所有软件功能都建立在ISA之上,ISA是最重要的层次

ISA指Instruction Set Architecture指令集体系结构,有时简称为指令系统
ISA是一种规约(Specification),它规定了如何使用硬件

  • 可执行的指令的集合,包括指令格式、操作种类以及每种操作对应的操作数的相应规定
  • 指令可以接受的操作数的类型
  • 操作数所能存放的寄存器组的结构,包括每个寄存器的名称、编号、
    长度和用途
  • 操作数所能存放的存储空间的大小和编址方式
  • 操作数在存储空间存放时按照大端还是小端方式存放
  • 指令获取操作数的方式,即寻址方式
  • 指令执行过程的控制方式,包括程序计数器(PC)、条件码示义等

当然,ISA是系统程序员需要深入理解的层次,应用程序员工作在由语言处理系统(主要是编译器和汇编器)的抽象层

数据的表示和存储

机器数:用0和1编码的计算机内部的0/1序列

数值数据表示的三要素:

  • 进位计数制

    十进制、二进制、十六进制、八进制数及其相互转换

  • 定、浮点表示(解决小数点)

    • 定点整数、定点小数
    • 浮点数(可用一个定点小数和一个定点整数来表示)
  • 如何用二进制编码(解决正负号)

    原码、补码、反码、移码(反码很少用)

在R进制数字系统中,应采用R个基本符号(0,1,2,...,R-1) 表示各位上的数字,采用“逢R进一”的运算规则,对于每一个数位 i, 该位上的权为Ri。R被称为该数字系统的基

  • 二进制:R=2,基本符号为0和1
  • 八进制:R=8,基本符号为0,1,2,3,4,5,6,7
  • 十进制:R=10,基本符号为0,1,2,3,4,5,6,7,8,9
  • 十六进制:R=16,基本符号为0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

八进制octal用后缀O表示,十六进制用后缀H或前缀0X表示,现代计算机系统多用十六进制表示机器数

R进制数转换为十进制数:按权展开

(10101.01)2=1x24+1x22+1x20+1x2-2=(21.25)10

a 的 -b 次方,实际上是 1 除以 (a 的 b 次方)

(307.6)8=3x82+7x80+6x8-1=(199.75)10

(3A. 1)16=3x161+10x160+1x16-1=(58.0625)10

十进制数转换为二进制,二进制转换为十六进制或八进制

十进制转八进制

整数:除基取余,下高上低

小数:乘基取整,下底上高

可能小数部分总得不到0,此时得到一个近似值,现实中的精确值可能在机器内部无法用0和1精确表示

数值数据中的小数点在计算机中只能通过约定小数点的位置来表示

  • 小数点位置约定在固定位置的数称为定点数
  • 小数点位置约定为可浮动的数称为浮点数

定点小数用来表示浮点数的尾数部分

定点整数用来表示整数(带符号整数和无符号整数)

任何实数:X=(-1)s ×M×RE

  • S取值为0或1,用来决定数X的符号
  • M是一个二进制定点小数 ,称为数X的尾数
  • E是一个二进制定点整数,称为数X的阶或指数
  • R是基数,可以为2、4和16等
  • 计算机中只要表示S、M和E三个信息,就能确定X的值,这就是浮点数

数值数据的表示

原码

  • 正号首位为0

  • 负号首位为1

  • 数值部分不变

    • 容易理解, 但是:
      1. 0的表示不唯一,故不利于程序员编程
      2. 加、减运算方式不统一
      3. 需额外对符号位进行处理,不利于硬件设计
  • 从50年代开始,整数都采用补码来表示,但浮点数的尾数用原码定点小数表示

移码

也被称为增码或偏置码,通常用于表示浮点数的阶码(指数)

将一个数值增加一个偏移常数(Excess/bias)来定义,当编码位数为n时,bias取2n-1或2n-1-1

当n=4,Ebiased=E+23

-8(+8)=0000B(移码表示)
0(+8)=1000B(移码表示)

0的移码表示是唯一的1000,当bias为2n-1时,移码和补码仅第一位不同

补码

在一个模运算系统中,一个数与它除以模后的余数等价

时钟是一个模12系统:10 - 4=10 + 8(mod12),- 4=8

  • 一个负数的补码等于模减该负数的绝对值,12 - 4 = 8
  • 对于某一确定的模,某数减去小于模的另一数,总可以用该数加上另一数负数的补码来代替

计算机中的运算器是模运算系统

0111 1111 - 0100 0000
= 0111 1111 + (28- 0100 0000)
= 0111 1111 + 1100 0000
= 1 0011 1111 (mod 28)
= 0011 1111

只留余数,1被丢弃

一个负数的补码等于将对应正数补码,各位取反、末位加一

补码的定义

假定补码有n位,则[X]补= 2n + X (-2n-1 ≤ X<2n-1 ,mod 2n) X是真值,[x]补是机器数

  • 正数符号位为0,数值部分不变
  • 负数符号位为1,数值部分各位取反,末位加1
  • 变形补码:双符号,用于存放可能溢出的中间结果

  • 8位无符号整数最大是255(1111 1111)
  • 8位带符号整数最大为127(0111 1111)

三种定点编码方式

  • 原码:定点小数,用来表示浮点数的尾数
  • 移码:定点整数,用于表示浮点数的阶(指数)
  • 补码:50年代以来,所有计算机都用补码来表示带符号整数
    • 补码运算系统是模运算系统,加、减运算统一
    • 数0的表示唯一,方便使用
    • 比原码多表示一个最小负数

非数值数据的编码表示

表示逻辑(关系)表达式中的逻辑值时用到逻辑数据

  • 表示:用1位表示,N位二进制数可表示N个逻辑数据
  • 运算:按位进行,|、&、^、<<、>>等
  • 识别:逻辑数据和数值数据在形式上并无差别,都是一串0/1序列, 计算机靠指令来识别

ASCLL码

  • A 65

  • a =65+32=97

    记住首字母就能推导其他32个字母在ASCLL码表中位置

汉字编码

  • 交换码

    交换码就是国标码,是计算机及其他设备之间交换信息的统一标准

    国标码也有一张码表,表中任意汉字或符号的区号和位号的组合,叫做这个汉字或符号的区位码

    机内码是计算机汉字系统中使用的二进制字符编码

    转换方式是先转换为十六进制

    • 国标码=区位码+2020H
    • 机内码=国标码+8080H
    • 机内码=区位码+A0A0H
    • 八进制是O,十进制是D,十六进制是H
  • 外码

    外码是汉字的输入编码

  • 内码

    内码是汉字的内部编码

    内码=国标码+8080H

  • 汉字字形码

    显示器或打印机输出汉字使用的代码

  • 汉字地址码

    是字库中存储的每个汉字的逻辑地址

需要2字节才能表示一个汉字内码是因为汉字总数超过6万字,216=65536

数据宽度和存储容量的单位

除比特和字节外,也经常使用字Word为单位

字和字长概念不同

  • 字长指数据通路(CPU内部数据流经的路径以及路径上的部件)的宽度,等于CPU内部总线的宽度、运算器的位数、通用寄存器的宽度(这些部件的宽度都是一致的)
  • 字表示被处理信息的单位,用来度量数据类型的宽度

容量单位1KB是210字节=1024B,1MB=220字节=1024KB

速度单位1Kbps是103/s=1000bps,1Mbps=106/s=1000Kbps

不同机器上表示的同一种类型的数据可能宽度不同,必须确定相应的机器级数据表示方式和相应的处理指令

同类型数据并不是所有机器都采用相同的宽度,分配的字节数随ISA、机器字长和编译器的不同而不同

  • 整数乘法运算比移位和加法等运算所用时间长,通常一次乘法运算需要多个时钟周期,而一次移位、加法和减法等运算只要一个或更少的时钟周期,因此编译器在处理变量与常数相乘时,往往以移位、加法和减法的组合运算来代替乘法运算
  • 对于整数除法运算,由于计算机中除法运算比较复杂,而且不能 用流水线方式实现,所以一次除法运算大致需要30个或更多个时 钟周期,比乘法指令的时间还要长,为了缩短除法运算的时间,编译器在处理一个变量与一个2的幂次形式的整数相除时,常采用右移运算来实现

链接概述和目标文件格式

预处理

处理源文件中以#开头的预编译指令

  • 删除#define并展开所定义的宏
  • 处理所有条件预编译指令
  • 插入头文件到#include
  • 删除所有的注释
  • 添加行号和文件名标识,以便编译时编译器产生调试用的行号信息

经过预编译处理后,得到的是预处理文件

编译

编译过程就是将预处理文件进行词法分析、语法分析、语义分析、优化后,生成汇编代码文件

用来进行编译处理的程序称为编译程序(编译器Compiler)

经过编译后得到汇编代码文件

汇编

汇编器将汇编语言源程序转换为机器指令序列

汇编指令和机器指令一一对应,前者是后者的符号表示,它们都属于机器级指令,所构成的程序称为机器级代码

汇编后得到可重定向目标文件

链接

链接过程是将多个可重定位目标文件合并以生成可执行目标文件

优点:

  • 模块化

    1. 一个程序可以分成很多源程序文件
    2. 可构建公共函数库,如数学库,标准C库等
  • 效率高

    1. 时间上可分开编译

      只需重新编译被修改的源程序文件,然后重新链接

    2. 空间上无需包含共享库所有代码

      源文件中无需包含共享库函数的源码,只要直接调用即可

      可执行文件和运行时的内存中只需包含所调用函数的代码 而不需要包含整个共享库

三类目标文件

  • 可重定位目标文件 (.o)

    其代码和数据可以和其他可重定位文件合并为可执行文件

    每个.o文件由对应的.c文件生成

    每个.o文件代码和数据地址都从0开始

  • 可执行目标文件 (Linux默认a.out,Windows*.exe)

    包含的代码和数据可以被直接复制到内存并被执行

    代码和数据地址为虚拟地址空间中的地址

  • 共享的目标文件 (Linux中的*.so)

    特殊的可重定位目标文件,能在装入或运行时被装入到内存并自动被链接,称为共享库文件

    Windows中称其为Dynamic Link Libraries,DLL

目标代码Object Code指编译器和汇编器处理源代码后所生成的机器语言目标代码

目标文件Object File指包含目标代码的文件

符号及符号表

符号解析

程序中有定义和引用的符号

  • 编译器将定义的符号存放在一个符号表节中
  • 符号表是一个结构数组
  • 每个表项包含符号名、长度和位置等信息
  • 编译器将符号的引用存放在重定向节中
  • 链接器将每个符号的引用都与一个确定的符号定义建立关联

重定位

  1. 将多个代码段与数据段分别合并为一个单独的代码段和数据段
  2. 计算每个定义的符号在虚拟地址空间中的绝对地址
  3. 将可执行文件中符号引用处的地址修改为重定位后的地址信息

三种链接器符号

每个可重定位目标模块m都有一个符号表,它包含了在m中定义和引用的 符号

  • Global symbols(模块内部定义的全局符号)

    由模块m定义并能被其他模块引用的符号

  • External symbols(外部定义的全局符号)

    由其他模块定义并被模块m引用的全局符号

  • Local symbols(本模块的局部符号)

    仅由模块m定义和引用的本地符号

链接器局部符号不是指程序中的局部变量(分配在栈中的临时性变量),链接器不关心这种局部变量

全局符号的强/弱特性

  • 函数名和已初始化的全局变量名是强符号

  • 未初始化的全局变量名是弱符号

链接器对符号的解析规则

  1. 强符号只能被定义一次,否则链接错误
  2. 若一个符号被定义为一次强符号和多次弱符号,则按强定义为准,对弱符号的引用被解析为其强定义符号
  3. 若有多个弱符号定义,则任选其中一个

符号解析时只能有一个确定的定义(即每个符号仅占一处存储空间)

advice:

  • 尽量避免使用全局变量
  • 一定需要用的话,就按以下规则使用
    1. 尽量使用本地变量static
    2. 全局变量要赋初值
    3. 外部全局变量要使用extern

cation:

多重定义全局变量会造成一些意想不到的错误,而且是默默发生的,编译系统不会警告,并会在程序执行很久后才能表现出来, 且远离错误引发处。特别是在一个具有几百个模块的大型软件中, 这类错误很难修正

不想深入了解链接器工作原理,就应该养成良好的编程习惯

重定位

符号解析完成后进行重定位

  1. 合并相同的节

    例如所有.text节合并作为可执行文件中的.text节

  2. 对定义符号进行重定位(确定地址)

    确定新节中所有定义符号在虚拟地址空间中的地址

    例如为函数确定首地址,进而确定每条指令的地址,为变量确定首地址

    完成这一步后,每条指令和每个全局或局部变量都可确定地址

  3. 对引用符号进行重定位(确定地址)