<<程序是怎么跑起来的>>学习笔记总结二
2.7 程序运行环境
- 最早的程序是需要直接操作硬件的,也就是说编写的程序除了需要的逻辑代码之外,还要把控制硬件代码也写进去,后面随着人们初步把这些公共代码抽离,就形成了操作系统
- 程序运行环境,包含硬件和操作系统. 操作系统就是操作硬件的程序,也是一个平台,让其他程序可以运行在操作系统之上,而不再需要直接操作硬件.现代操作系统为了安全,很多已经禁止直接的硬件操作行为
- 现代计算机组成:
CPU,内存,外部IO设备如鼠标,键盘,屏幕,打印机,磁盘等等
- 操作系统出现之后,也结束了程序员需要适配不同硬件平台的问题,都由操作系统去适配,代码API则是统一一套,节约了很多精力. 这也是很多软件设计的思想,没有什么问题是添加一层分层无法解决的,除了层级过多这个问题本身
- 软件多平台兼容性,也有使用中间代码和平台的如浏览器, JVM设计思路就是如此.
- BIOS(basic IO system),用来做硬件自检和引导程序启动功能的; bootstrap本意就是鞋子后面的布带,一个小提手
2.8 代码编译和链接
- 计算机无法直接运行源代码,不管是C,shell,js, python等等,最终都需要变成可执行二进制代码
- 编译步骤分为: 预处理,编译,汇编,链接4个大阶段
编译分为: 词法分析,语法分析,语义分析和中间代码生成, 中间代码优化,目标代码生成5个阶段
目标代码生成因为不同的硬件平台,所以中间代码环节是很重要的,意味着只需要在目标代码生成这个环节做多平台兼容处理,可以节省很多工作.
这种解决问题思路可以用在软件开发的各个环节,就是讲工作拆解,这样一旦有变化,不需要整体改动,只需要改动对应环节即可,大大增加代码灵活性
注意一般是一个代码文件生成一个目标代码文件,如.obj .class, 但实际程序可能会有很多个,这时候就需要将这些目标代码文件链接在一起.这个一般是链接器来解决.链接,可以分为静态链接和动态链接, 顾名思义,静态链接就是编译时就链接进去,动态链接则是运行时或者运行前链接进去,类似懒加载方式. DLL就是为了解决程序之间公共代码冗余而专门抽离出来,也可以节约内存消耗.
- 编译时,虚拟内存地址以及执行时真实内存地址,这时候有一个地址转换,这也是为什么会有基地址的原因.
- 内存中程序占用: 存储变量,存储函数, 栈, 堆
2.9 操作系统和应用程序关系
- 操作系统是运行在硬件层之上, 也是一个平台; 应用程序则运行在操作系统之上
- 系统调用, 就是操作系统提供统一API接口, 程序直接调用, 操作系统保证行为和返回数据一致性,而程序员不用关心平台差异性.
- 程序可移植性,也是一样. 只要是在对应操作系统上验证可用,则可以运行在相同操作系统的不同机器上,而不用关心其硬件差异.
目前来说,一般都是相同操作系统具备移植性
但基于软件平台的,则可以跨操作系统如浏览器, JVM, 容器等等
- what you see is what you get,就是所见即所得, 这一点其实贯穿整个软件开发设计中,就是尽量让程序和结果之间关系简单直白一些,文档,注释,说明,引导,GUI图形化界面,提示等等都是为了达到这个目的
- 多任务, 也就是时间片机制. 以前都是单核CPU,为了可以同时运行多个任务,这时候将CPU的执行时间切片,每个任务轮流得到这个执行时间,这样表面看就是多个任务同时执行.
2.10 汇编语言
- .asm就是汇编文件后缀
- C语言可以和汇编代码混编,汇编代码是由助记符来帮助记忆和使用的
- 汇编代码和本地机器代码是一一对应的
- 汇编和反汇编, 前者就是把代码转为汇编语言代码, 后者则相反. 汇编器就是执行前者的工具,也有的汇编器可以执行后者
- 段定义,segment和end标记, 是构成程序的命令和数据的几何体加一个名字得到的
_TEXT
_DATA
_BSS
从上可以看到, 代码段,数据段,未初始化全局变量数据段是怎么来的了
- 过程procudure
proc和endp包起来的,相当于函数的形式,就叫做过程
- 汇编语言形式:
操作码和操作数
mov
add
push
pop
call
ret
- 寄存器
eax 累加寄存器
ebx 基址寄存器
ecx 计数寄存器
edx 数据计数器
esi 源基址寄存器
edi 目标基址寄存器
ebp 扩展基址指针寄存器
esp 扩展栈指针寄存器x86 的32位寄存器都带了e,扩展的意思,因为16位名称是不带e的.这是为了区分
注意因为本身x86最开始是从8位,16位硬件开始扩展和设计的,这是为了兼容处理
- 函数调用
call
ret
注意在这个过程中,栈就是保存局部变量和信息的地方,调用结束则会清空栈中数据
- 全局变量和局部变量
注意生命周期不同, 使用方式不同, 管理方式也不同
变量如果寄存器空间足够则放在寄存器,不够则用栈存放;因为寄存器访问速度快得多
- 流程控制
goto
call
ret
cmp
jl(jump on less than)
jle
jge
jg
2.11 硬件控制
- windows提供系统调用方式访问硬件,直接操作硬件在目前2020年的操作系统中越来越少,主要是安全考量.
- 不过IOT物联网兴起,一些专用操作系统在硬件调用上是越来越便捷
- IO设备都是通过IO控制器进行访问和操作的, IO设备也是通过端口号进行区分的
- 外围设备和中断请求, IRQ, interrupt request. 就是终端当前运行程序,转到其他程序运行的必要机制
中断机制, 可以让程序快速响应各个任务,由于CPU执行速度较快,临时中断然后任务切换, 处理完成后再切换回去也很快,对外来说可能都是无感知的
外围设备的中断请求会使用不同于IO设备的端口其他编号,称之为中断编号
- 应对外围设备状态变化
轮询,太消耗资源
中断,比较合适,相当于主动发起请求,CPU响应即可
- DMA
就是外围设备数据直接加载到内存,不经过CPU转换
类似的, GPU目前也支持直接从固态硬盘加载数据到显存中,不需要经过CPU
- VRAM
vedio ram, 视频内存
2.12 计算机最简化智能
- 计算机发明出来就是帮助人类解决问题,而最终极的问题就是替代人类工作并思考–AI
- 计算机本身没有思考能力,但可以通过训练,让计算机能够在某些场景下像人类一样进行问题处理.这就是机器学习和人工智能.
注意这里,只是表现得跟人类一样,并不代表具备了真正的思考能力
- 例如人分辨一个动物是猫还是狗,其实就是提取了各种信息, 而计算机也可以通过训练,达到人类多少百分比的分辨能力,甚至可以超出人类的分辨能力
- 只不过,人类其实最厉害的就是学习和适应能力,制造工具能力. 而计算机目前要达到电影中的替代人类,还有很长的路要走,甚至永不可能达到.