程序是怎么跑起来的
简介
- 作者: 矢泽久雄
CPU
- 程序运行流程
graph TD A[高级语言编写程序] -->|编译| B[机器语言的EXE文件] B --> C[程序运行时,内存中生成EXE副本] C --> D[CPU解释并执行]
-
CPU构成
- 寄存器 用来暂存指令、数据
- 控制器 把内存上的指令、数据读入寄存器,并根据指令的执行结果来控制整个计算器
- 运算器 运算从内存读入寄存器的数据
- 时钟 发出CPU开始计时的时钟信号
- 机器语言 -> 汇编语言 -> 高级语言
函数的调用机制: 栈
- call指令
- return指令
- 程序在内存里的构成
- 指令区域
- 数据区域
- 栈区域
数据
- 进制
- 基数
- 位权
-
移位运算
-
补码 = 反码 + 1 用来表示负数
补码 + 源码 = 0
浮点数
-
构造 \(\pm m \times n^e\)
-
符号 正数或者负数
-
尾数 m 尾数部分采用将小数点前部分固定位1的方式
-
基数 n 指数部分采用Excess系统,表示负数时不使用符号位
-
指数 e
-
-
具体情况
- double 1位符号位 + 11位基数位 + 52位尾数位
- float 1位符号位 + 8位基数位 + 23位尾数位
-
如何保证小数无误差
- 转换为整数计算
- 使用4位来表示0-9的1位数字
内存
- 内存地址 指针
- 常见数据结构
- 数组
- 栈
- 队列
- 环形缓冲区
- 链表
- 二叉查找树
磁盘
-
磁盘缓存
-
虚拟内存
-
动态链接和静态链接
动态链接 程序运行时动态加载Library,多个应用共有一个DLL文件,从而节约内存,同时也可以通过只更新DLL,无需更新整个exe文件来更新程序。
-
物理构造
- 磁道
- 簇 Windows 逻辑读写的最小单位
- 扇区 磁盘物理读写的最小单位
-
单位
信息存储单位
- bit 位
- byte B 字节 = 8 bit
- word 字 CPU占据一个单独的地址 = 8 byte (x64) or 4 byte (x86) 类似 golang的 int
- byte B 字节
- KB
- MB
- GB
- TB
- PB
-
压缩算法
案例
- RLE 行程长度算法
- 哈夫曼编码
分类
可逆 不可逆
运行环境
-
操作系统
作用
- 克服了CPU以外的硬件差异
- 提供了API来操作硬件
如何克服硬件和操作系统差异
- FreeBSD Ports 根据硬件环境来编译应用的源代码 移植
- 虚拟机
- 字节码 + 虚拟机 如 Java,dotnet, golang
BIOS 启动操作系统
-
硬件
如何得到可执行文件(c语言)
-
编译 源代码 -> 目标文件
-
链接 目标文件 + 静态链接库 + 导入库 -> 可执行文件
-
执行 可执行文件 + 动态链接库
EXE 文件中给变量以及函数分配了虚拟的内存地址
内存分区
-
操作系统
-
复制EXE文件
- 用于变量的空间
- 用于函数的空间
-
程序运行时分配的空间
-
用于栈的空间
存储函数内部临时使用的变量,以及函数调用所用的参数的内存区域
-
用于堆的空间
用来存储程序运行时的任意数据以及对象的内存领域
-
操作系统和应用的关系
应用程序经过OS间接的控制硬件
- 系统调用
- API
通过汇编理解函数执行过程
CPU将内存中的指令和数据读出,存储到CPU内部的寄存器中进行处理。
-
x86主要寄存器
寄存器名 名称 主要工作 eax 累加寄存器 运算 ebx 基址寄存器 存储内存地址 ecx 计数寄存器 计算循环次数 edx 数据寄存器 存储数据 esi 源基址寄存器 存储数据发送源的内存地址 edi 目标基址寄存器 存储数据发送目标的内存地址 ebp 扩展基址指针寄存器 存储数据存储领域基点的内存地址 esp 扩展栈指针寄存器 存储栈最高位数据的内存地址 -
常见指令
- mov
- cmp jmp 条件 循环
- push pop
- in out 处理某端口号硬件的输入输出
-
中断 用来处理实时数据
-
DMA 数据不经过CPU,直接从外设到主内存
-
显示
- VRAM
- GPU
随机数生成
- 伪随机数
- 种子
- 随机数生成算法