《程序是怎样跑起来的》读书笔记1——对程序员来说CPU是什么
一丶什么是程序
程序是指令和数组的组合体,如:print("你好世界"),其中print是指令,你好世界是数据。
CPU能直接识别和执行的只有机器语言,使用C,java这种高级语言编写的程序需要编译转换后才可以运行。
二丶CPU的内部结构
CPU即中央处理器,相当于计算机的大脑,内部由许多晶体管构成,负责解释和运行最终转换成的机器语言程序。
- 寄存器:暂存指令和数据等处理对象。
- 控制器:负责把内存上指令,数据等读入寄存器,并根据指令的执行结果来控制整个计算机。
- 运算器:负责运算从内存读入到寄存器的数据
- 时钟:负责发起cpu开始计时的时钟信号,时钟信号频率单位为赫兹,频率越高CPU运算速度越快。
程序启动后,根据时钟信号,控制器会从内存中读取指令和数据,通过对这些指令加以解释和运行,运算器会对数据进行运算,控制器根据计算结果来控制计算机(控制:除了数据运算之外的处理,比如内存和磁盘等输入输出设备,显示器,打印机等的输出)
三丶寄存器
1.为什么需要寄存器
CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存
,但是数据在缓存中地址并不固定,cpu每次读写缓存都需要寻址,为了减少寻址的开销,最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据
2.从一段汇编开始了解寄存器
mov eax, dword ptr [ebp-8] #将数值从内存赋值到eax寄存器
add eax, dword ptr [ebp-0ch] #eax的数值和内存的数值相加
mov eax, dword ptr [ebp-4],eax #把eax的数值(上一步计算的结果)存储到内存中
使用高级语言编写的程序在编译后转化为机器语言,机器语言基本上和汇编一一对应。
上面代码中 eax
,ebp
都是寄存器的名称,
种类 | 功能 |
---|---|
累加寄存器 | 存储执行运算的数据和运算后的数据 |
标志寄存器 | 存储运算处理后cpu的状态 |
程序计数器 | 存储下一条指令所在的内存地址 |
基址寄存器 | 存储数据内存的起始地址 |
变址寄存器 | 存储基址寄存器的相对位置 |
通用寄存器 | 存储任意数据 |
指令寄存器 | 存储指令,cpu内部使用,程序员无法修改 |
栈寄存器 | 存储栈区域的起始地址 |
其中程序计数器,累加寄存器,标志寄存器,指令寄存器和栈寄存器只有一个,其他的寄存器一般存在多个。
对于程序员来说只需要理解寄存器的作用,cpu是一组寄存器的组合
3.程序计数器
程序启动后,操作系统会将硬盘中保存的程序复制到内存中,命令和数据通常被存储到多个地址上,操作系统在复制程序到内存的时候,会将程序计数器设定为起始位置,CPU每执行一个指令,程序计数器就会自动加上1,因此CPU会依据程序计数器的数值从内存读取命令并执行
。
4.条件分支和循环机制是怎么 实现的
条件分支和循环中使用跳转指令
,需要参照当前执行的运算结果来判断是否跳转,其中标志寄存器会保存当前计算的结果,条件分支在跳转指令钱会进行比较运算,至于是否执行跳转指令,则由cpu参考标志计算器的内容后进行判断。
5.函数的调用机制
调用函数的本质是将程序计数器设置为函数的存储地址
。不过这和条件循环分支不同,因为丹村的跳转指令没办法实现函数的调用,函数调用结束后需要回到原本的调用点。
机器语言使用call
,return
指令解决这个问题,调用函数使用call指令,call指令会将要执行的指令地址存储到栈内存中。
函数处理完毕后,再通过函数的出口执行return指令,return指令会将栈中地址设定到程序计数中。