《程序是怎样跑起来的》---第一章:CPU是什么?

一、先导问题

  1. 程序是什么?

指令的集合

  1. 程序由什么组成?

指令和数据

  1. 什么是机器语言?

CPU可以直接识别并解释执行的语言

  1. 正在运行的程序存储在什么位置?

内存

  1. 什么时内存地址?

用于表示内存中存储指令与数据的存储位置的数值

  1. 计算机构成元件中,负责程序的解释和运行的是哪个?

CPU

二、主要内容

【一】 CPU内部结构
  1. 寄存器(重点)

(1)暂存由内存复制过来的指令与数据等处理对象,可以看成内存的一种。
(2)种类多样,每一种有不同的用途,下小节会介绍。

  1. 控制器

(1)负责把内存上的数据与指令等处理对象读入寄存器。
(2)根据指令的执行结果控制整个计算机。
(3)”控制“表示除数据运算以外的处理,主要为输入输出的时机控制,如内存硬盘的读写,鼠标键盘的输入,显示器打印机的输出等。

  1. 运算器

(1)运算寄存器中的数据,寄存器的数据来自于内存。

  1. 时钟

(1)向CPU发送时钟计时信号

对内存的简单解释

(1)内存通常来说指计算机的主存储器,简称主存。通过控制芯片等与CPU相连,主要负责存储数据与指令,由可读写元素构成,每个字节都带有地址编号。CPU通过该地址读取数据与指令到寄存器,或者写入数据至内存。
(2)主存中存储的指令与数据会根据计算机的关机而删除(DRAM)。

DRAM:动态随机存取存储器,RAM可进行读写,速度快,非长久保存
ROM:只读存储器,可永久保存,断电不会刷新数据,类似硬盘技术

程序运行机制的简单解释
  1. 使用高级编程语言编写程序
  2. 程序编译成为机器语言的exe文件,保存在硬盘中

编译:使用编译器,将高级语言转换成为机器语言的过程
汇编:使用汇编器,将汇编语言(低级语言)转换为机器语言的过程

  1. 程序运行时,内存中生成exe文件副本
  2. CPU通过控制器将指令与数据暂存至寄存器
  3. 控制器执行寄存器中的指令
  4. 运算器根据控制器的控制,计算寄存器中的数据
  5. 控制器根据运算器的结果进一步控制计算机

【二】 CPU是寄存器的集合体

程序是将寄存器当作对象来描述的。

(1)内存的存储场所通过地址区分,寄存器种类通过名字区分
(2)汇编中直接通过寄存器名字操作寄存器以及其中的数据,将寄存器视为一个可操作对象,而不再对其进行拆分。

寄存器种类

由于“数据”可分为:1.表示内存地址的数值 2.表示用于运算的数值,因此存储数据和指令的寄存器也分为不同种类。

寄存器种类


【三】 决定程序流程的程序计数器

通过程序流程直观感受程序计数器对于程序运行的控制:
以顺序执行的程序为例(不含函数调用与分支循环)

  1. 用户发出运行程序的指令
  2. 操作系统将保存在硬盘中的程序复制到内存中
  3. 内存通过地址划分存储区域,假设程序在内存中起始地址0100
  4. 操作系统将程序复制到内存后,将程序计数器(CPU寄存器的一种)设定为程序的起始地址0100
  5. CPU控制器根据程序计数器保存的数据,找到内存0100地址中的指令进行执行
  6. 控制器执行这一指令后,程序计数器加一,指向内存地址0101,即程序在内存中的下一指令。加一操作是默认所执行的指令占用了一个内存地址,若指令占用了n个内存地址,则程序计数器增加n
  7. 控制器不断执行程序计数器所指向的指令,程序计数器不断变化,最终执行完程序
【四】 条件分支与循环机制

1.顺序执行:按照地址内容顺序执行指令
2.条件分支:按照条件执行任意特性地址的指令
3.循环执行:重复执行某一地址或某些地址的指令

以条件分支为例:0102指令为jump(跳转)指令,跳转0104

  1. 程序起始位置0100,程序计数器设定0100,控制器执行0100指令
  2. 0100执行完毕,程序计数器加1,控制器执行0101指令
  3. 0101执行完毕,程序计数器加1,控制器执行0102指令,0102指令通过标志寄存器进行条件判断,假设满足跳转条件,jump指令跳转至0104,间接执行将程序计数器设定为0104的操作
  4. 控制器执行0104

标志寄存器:保存累加寄存器的结果状态(正零负),同样保存溢出与奇偶校验的结果。

(1)溢出:验证运算结果是否超出寄存器长度范围
(2)奇偶校验:验证运算结果的值是奇数还是偶数
(3)正零负:32位寄存器(0-31)的后三位(0、1、2)为1时分别表示运算结果为正数、零、复数

CPU比较机制:例:累加寄存器中XXX与通用寄存器YYY进行比较:

(1)CPU内部(暗中)将XXX与YYY进行减法运算
(2)将XXX-YYY结果保存到标志寄存器中,标志寄存器为正则XXX大,为负则YYY大,为0则二者相等。


【五】函数的调用机制

函数调用机制与条件分支、循环机制的不同: 即为什么函数调用无法使用jump指令进行跳转。

以函数调用流程举例,因为一行代码往往对应多条指令,所以一行代码所直接对应的地址是离散的,例如程序起始位置的第一行代码对应地址0100,而第二行代码对应的地址是0123而不是0101,不过为了演示方便我还是按一个地址对应一行代码进行演示:
(1)程序起始位置0100,与控制器配合,执行到0102
(2)此时程序计数器内数据为0102,对应指令为函数调用,使用jump指令跳转至函数入口0145,执行代码体内容
(3)函数执行完毕,此时程序计数器指向函数末尾地址0155期望结果是程序计数器设定为调用函数指令0102的下一条指令0103, 但是实际上,jump命令无法做到这一点。

为什么jump指令可以做到分支循环的回溯,而无法做到函数的返回呢?

(1)在条件分支或循环中,程序可由0102跳转至0104,也可由0108(循环体末尾)跳转回0102,因为0102指令指明了跳转的地址为0104,当循环体执行完毕后,0108地址同样指明了跳转回0102
(2)在函数调用中,0102调用函数,进入函数入口0145,执行完函数体后,0155指令并没有指明返回的地址为0103,因此无法完成跳转。

因此需要设计一组指令,完成函数跳转与函数返回,这个过程

call与return

(1)call:在函数入口设定到程序计数器之前,将函数调用指令的下一条指令地址放入名为栈的主存中。
(2)return:当函数体执行完毕后,将栈中的后续地址设定到程序计数器中,完成函数的返回跳转。


【六】类似数组的基址与变址寄存器

理解起来很简单,数组就是内存中一段连续排列的数据结构,通常使用数组名表示数组的起始位置,通过索引表示元素的相对位置,即相对起始位置的偏移量。
基址寄存器保存基址,类似数组名,变址寄存器保存偏移量,类似索引
如:基址寄存器:0100,变址寄存器:0036
实际内存地址=基址寄存器+变址寄存器 0136

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值