注:本系列内容为阅读《程序是怎样跑起来的》书籍后的记录笔记,部分内容参考于书中,转载请注明出处。
第一章 CPU是什么
1.1 CPU构成
CPU构成:CPU是由寄存器、控制器、运算器和时钟四个部分构成。
- 寄存器:可用来暂存指令、数据等处理对象,可以将其看做是内存的一种。
- 控制器:负责把内存上的指令、数据等读入寄存器,并根据指令的执行结果来控制整个计算机。
- 运算器:负责运算从内存读入寄存器的数据。
- 时钟:负责发出CPU开始计时的时钟信号。(部分CPU的时钟位于CPU外部)
CPU简易工作流程:程序启动后,根据时钟信号,控制器会从内存(DRAM)中读取指令和数据。通过对这些指令加以解释和运行,运算器就会对数据进行运算,控制器根据该运算结果来控制计算机。
词条解释:
- 高级编程语言:能够使用类似于人类语言语法来记述的语言,如BASIC、C、C++、OC等
- 低级编程语言:与高级编程语言相对,包括机器语言和汇编语言。
- 汇编语言:采用助记符来编写程序的语言,有时也称之为汇编。
- 助记符:通常为指令功能的英文单词的简写,比如mov和add分别是数据的存储(move)和相加(addition)的简写。
- 汇编:通常将汇编语言编写的程序转化成机器语言的过程称之为汇编。
- 反汇编:机器语言程序转化成汇编语言程序的过程则称之为反汇编。
- 编译:将使用高级编程语言编写的程序转换为机器语言的过程。
1.2 寄存器的重要性
对于程序员来说,CPU可以看做是具有各种功能的寄存器的集合体。
寄存器种类:
- 累加寄存器:只有一个,存储执行运算的数据和运算后的数据。
- 标志寄存器:只有一个,存储运算处理后的CPU的状态。
- 程序计数器:只有一个,存储下一条指令所在内存的地址。
- 栈 寄 存 器 :只有一个,存储栈区域的起始地址。
- 指令寄存器:只有一个,存储指令。CPU内部使用,程序员无法通过程序对该寄存器进行读写操作。
- 基址寄存器:多个,存储数据内存的起始地址。
- 变址寄存器:多个,存储基址寄存器的相对地址。
- 通用寄存器:多个,存储任意数据。
词条解释:
溢出:是指运算的结果超出了寄存器的长度范围。
1.3 程序计数器
程序计数器决定着程序的执行流程。
CPU每执行一个指令,程序计数器的值就会加1,然后CPU的控制器就会参照程序计数器的数值,从内存中读取命令并执行。
1.4 条件分支和循环分支
程序的流程分为顺序执行、条件分支和循环三种。
- 顺序执行:按照命令地址内容的顺序执行指令。每次执行一个指令程序,程序计数器的值就自动加1。
- 条件分支:是指根据条件执行任意命令地址的指令。程序计数器执行跳转指令,程序计数器的值指向任意指定值。
- 循环执行:是指重复执行同一命令地址的指令。程序计数器执行跳转指令,程序计数器的值指向任意指定值。
CPU在进行运算时,标志寄存器的值会根据运算结果自动设定。条件、循环分支在跳转指令前会比较运算,是否执行跳转指令,由CPU在参考标志寄存器的数值后进行判断。
运算结果的正、负和零三种状态是由标志寄存器的三个位表示。
以32位CPU(寄存器的长度是32位)的标志寄存器为例,如图:
CPU的比较机制,就是一个数减去另一个数,然后将结果保存到标志寄存器中。
1.5 函数的调用机制
为了处理在函数内部处理完成后,处理流程(程序计数器)能够再返回到函数调用点继续执行,机器语言采用的是call指令和return指令。
在将函数的入口地址设定到程序计数器之前,call指令会把调用函数后要执行的指令的地址存储在栈内存中。函数处理完毕后,再通过函数的出口来执行return指令,把存储在栈中的指令地址设定到程序计数器中。
1.6 通过地址和索引实现数组
数组的实际地址 = 基址寄存器(固定) + 变址寄存器(变化)
1000 0000 = 1000 0000 + 0000 0000
1000 0001 = 1000 0000 + 0000 0001
1000 0002 = 1000 0000 + 0000 0002
变址寄存器相当于高级编程语言中数组的索引功能。
1.7 机器语言的指令
机器语言指令的主要类型和功能:
类型 | 功能 |
---|---|
数据传送指令 | 寄存器和内存、内存和内存、寄存器和外围设备之间的数据读写和操作 |
运算指令 | 用累加寄存器执行算数运算、逻辑运算、比较运算和移位运算 |
跳转指令 | 实现条件分支、循环和强制跳转等 |
call\return指令 | 函数的调用、返回调用前的地址 |