《程序是怎样跑起来的》总结一二三四章

一:
物理层面: CPU由具有开关功能的晶体管构成
逻辑层面: 内部由、寄存器,控制器,运算器,时钟四个部分构成,各部分通过电信号相互连通
程序启动后,根据时钟信号,控制器会从内存中读取指令与数据,通过对这些指令进行解释执行,运算器对数据进行运算,控制器根据运算结果来控制计算机
控制器: 负责把内存上的指令、数据等读入寄存器,并根据指令的运行结果来控制整个计算机
运算器: 负责运算从内存读入寄存器的数据
时钟: 负责发出cpu开始计时信号(时钟信号,该部件也可以放在cpu外部),时钟信号频率越高,cpu运行越快

寄存器:累加寄存器 存储执行运算的数据和运算后的数据,(只有一个)
标志寄存器 存储运算处理后的CPU的状态 (只有一个)
程序计数器 存储下一条指令所在内存的地址 (只有一个)
基址寄存器 存储数据内存的起始地址 (存在多个)
变址寄存器 存储基址寄存器的相对地址 (存在多个)
通用寄存器 存储任意数据 (存在多个)
指令寄存器 存储指令,CPU内部使用,程序员无法通过程序对该寄存器进行读写操作 ,所以一般不需要关注(只有一个)
栈寄存器 存储栈区域的起始地址 (只有一个)
寄存器可以存放指令,也可以存放数据,其中数据分为用于运算的数值与表示内存地址的数值两种,同时每个寄存器的功能都不同,
用于计算的数据存放在累加寄存器,内存地址放在基址寄存器与变址寄存器

程序计数器决定着程序的执行流程

通过基址寄存器与变址寄存器,可以对内存上特定的区域进行划分,实现类似数组的操作
例如: 查看10000000----1000FFFF地址时,将10000000存入基址寄存器, 在使变址寄存器的值在0000000—0000FFFF变化,cpu会将
基址寄存器+变址寄存器的值作为实际的内存地址,因为就实现了类似数组的功能,基址寄存器相当于数组的起始地址,变值寄存器相当于数组的索引。

条件分支: 根据条件执行任意地址的指令,将程序计数器的值设置为任意地址
循环: 重复执行同一地址的指令,程序计数器的值每次都设置为同一地址
分支与循环的实现机制为使用跳转指令实现,会参照当前执行的运算结果标志寄存器的值进行比较运算做减法来判断是否跳转

函数在调用完后,处理流程需要回到函数的调用点(函数调用指令的下一地址)
在计算机中,机器语言借用栈内存使用call指令与return指令进行函数的调用与返回
call指令: 函数调用时使用该指令,该指令会在程序计数器值变为函数入口地址前,将调用函数后要执行的指令地址存储在栈中
return指令: 函数执行完毕后,通过在函数的出口执行该指令,将保存在栈中的地址设定到程序计数器中实现回到调用地址

数据转送指令 寄存器与内存、内存与内存、寄存器和外围设备之间的数据读写操作
运算指令 用累加寄存器执行算术运算、逻辑运算、比较运算、移位运算
跳转指令 实现条件分支、循环、强制跳转
call/return指令 函数的调用、返回函数调用前的地址
二:
为什么要用二进制表示数据?
原因: 由于IC(集成电路) 的所有引脚只有直流电压0V或5V两个状态(也就是每个引脚只能表示两个状态),由于这个特性,因此决定了在计算机中的信息数据只能使用二进制来处理表示 注意: 现在IC大部分电压为为+5V,因此存在三种状态,0V/5V/高阻抗状态(不接收电流信号)

在计算机中只存在加法,因此减法也使用加法表示,a-3 = a + (-3),为此在使用负数时,就使用补数表示(用正数来表示负数)
负数==补数(按位取反+1),负数时最高位作为符号位,为1表示负数,为0表示正数
因此,右移后高位数有可能为1或者0填充空出来的数值,列如:-1在计算机中表示为111111111
补数的计算:进二机制数的各位数的数值按位取反,然后在将结果加1即可得到补数
按位取反: 把二进制数各数位的0变为1,1变为0,如00000001取反后11111110

两种右移的区别
逻辑右移: 当二进制数的值表示图形模式而非数值模式时,移位后需要在最高位补0,这就是逻辑右移,类似霓虹灯往右滚动的效果
算术右移: 将二进制数作为带符号的数值进行运算时,移位后要在高位补0或者1,如果数值是用补数表示的负数值,那么右移后在空出来的高位补1
三:
与二进制表示整数类似,二进制表示小数部分的转换方法也是小数位各数值乘以位权相加表示

浮点数: 用符号、尾数、基数、指数这4部分来表示的小数就是浮点数

实际中由于二进制位数太多,通常也会使用十六进制进行表示,二进制的4位数表示一位十六进制 ps:本人还在摸索中 (* ̄(oo) ̄)
四:
内存: 一种IC电子元件,常见DRAM(需要经常刷新保存数据)、SRAM(不需要刷新电路既可以保存数据),可以读取与写入,ROM(只能用来读取的内存)等形式
内存物理组成: 电源、地址信号、数据信号、控制信号,用来输入输出的IC引脚(通过为引脚指定地址,进行数据读取)

地址信号引脚数决定了内存能够表示的地址范围:表示地址范围 = 2^地址信号引脚数(次方)
数据信号引脚数决定了一次能够输入输出多少字节的数据(8位=1字节)输入输出数据字节数 = 数据信号引脚数/8(一个引脚表示一位二进制)
控制信号: 该信号引脚主要负责表示数据的读写

写入流程: 使用地址信号引脚指定数据的存储场所,把数据输入给数据信号引脚,把控制信号引脚写入信号置为1,执行完改流程数据写入内存结束
读取流程: 使用地址信号引脚指定数据的存储场所,把控制信号引脚读取信号置为1,执行完改流程后,数据会被输出到数据信号引脚,读取结束
禁止读写: 当控制信号读、写引脚同时置0时,无法进行读写

内存的逻辑模型: 内存类似楼房,在这栋楼房中,1层可以存储1字节的数据(内存为1kb时,且有1024层),楼层号表示的就是地址
指针变量存储数据的内存地址,通过使用它可以对任意指定地址的数据进行读写,指针的数据类型,表示一次可以读写的长度
数组: 多个同样数据类型的数据在内存中连续排列的形式,作为数组元素的各个数据通过连续的编号区分开,这个编号就是数组的索引

栈: 读写数据时,先入后出
队列: 先入先出(一般以环形缓冲区的方式实现,模型,是连接数组的头尾,使其成为一个环形进行读取)
在程序中实现栈与队列,需要以适当的元素数定义一个用来存储数据的数组,以及对该数组进行读写的函数对(入栈、出栈、入队、出队)

使用链表与二叉查找树的优势: 使用链表可以对数组数据进行高效添加删除,使用二叉查找树可以高效的读数据数据进行查找
链表实现: 在数组的基础上,在数组的个元素中除了数据的数值外还为其附带上下一个元素的索引,即可实现链表
二叉查找树: 在链表的基础上,往数组追加数据时考虑数据的大小关系,需要追加的数数值比先前保存的数值大放右边,小放左边(逻辑上实现,实际的内存不会分为两个方向),因为由链表编写而来,因此追加删除同样高效

posted @ 2024-02-16 21:45  王豪博  阅读(7)  评论(0编辑  收藏  举报