计组笔记(不定期持续更新)


菜鸟一个,

请随意批评。

前言

这只是笔者小羽在学习过程中的学习笔记,且不对计组进行深入探讨,内容偏概括,有些小羽认为自己比较熟知的或者只需了解知识点由关键词一笔带过。所以仅供参考。

(本篇将会持续更新~)

第一章 对程序员来说 CPU 是什么

1.1 CPU的内部结构解析

CPU 和 内存是由许多晶体管组成的电子部件,通常称为IC(Intergrated Circuit,集成电路)
从功能方面——CPU内部由寄存器、控制器、运算器、和时钟四个部分构成,各部分之间由电流信号相互连通

寄存器:用来暂存指令、数据等处理对象,可将其看作是内存的一种。根据种类不同,一个CPU内部会有 20~100 个寄存器
控制器:负责把内存上的指令、数据等读入寄存器,并根据指令的执行结果来控制整个计算机
运算器:负责运算从内存读入寄存器的数据
时钟:负责发出CPU开始计时的时钟信号。也有的计算机的时钟是位于CPU外部的

通常说的内存 指计算机的主存储器(main memory),简称主存
计算机关机-主存中存储的指令和数据会自动清除

1.2 CPU是寄存器的集合体

汇编语言采用助记符来编写程序
汇编——将汇编语言编写的程序转化为机器语言的过程
反汇编——反之

寄存器中存储的内容——指令和数据
数据分为——“用于运算的数值”和“表示内存地址的数值”
数据不同,存储其数值的寄存器也不同
CPU中每个寄存器的功能都是不同的——用于运算的数值放在累加寄存器中存储,表示内存地址的数值则放在基址寄存器和变址寄存器中存储

寄存器:(大致分为8类)
累加寄存器——存储执行运算的数据和运算后的数据
标志寄存器——存储运算处理后的CPU的状态
程序计数器——存储下一条指令所在内存的地址
基址寄存器——存储数据内存的起始地址
变址寄存器——存储基址寄存器的相对地址
通用寄存器——存储任意数据
指令寄存器——存储指令。CPU内部使用,程序员无法通过程序对该寄存器进行读写操作
栈寄存器——存储栈区域的起始地址

1.3 决定程序流程的程序计数器

程序计数器决定程序的流程

1.4 条件分支和循环机制

程序的流程——顺序执行、条件分支和循环
条件分支和循环——跳转指令,结果值存在标志寄存器中
在跳转指令前会进行比较运算,就是在CPU内部做减法运算,看结果值决定是否跳转

1.5 函数的调用机制

函数调用处理——通过程序计数器的值设定成函数的存储地址来实现
单纯的跳转指令无法实现函数的调用,
使用机器语言的 call指令 和 return指令 解决
call指令——把调用函数后要执行的指令地址存储在名为的主存内
return指令——把保存在栈中的地址设定到程序计数器中

1.6 通过地址和索引实现数组

通过基址和变址寄存器,就可对主内存上特定的内存区域进行划分,从而实现类似于数组的操作
实际内存地址 = 基址 + 变址寄存器
变指寄存器的值 = 高级编程语言程序中数组的索引功能

1.7 CPU的处理其实很简单

机器语言指令的主要类型
数据传送指令——寄存器和内存、内存和内存、寄存器和外围设备之间的数据读写操作
运算指令——用累加寄存器执行算数运算、逻辑运算、比较运算和移位运算
跳转指令——实现条件分支、循环、强制跳转等
call/return 指令——函数的调用/返回调用前的地址

第二章 数据是用二进制数表示的

2.1 用二进制数表示计算机信息的原因

IC 分为:模拟IC 和 数字IC(*)
cpu和内存是IC的一种
IC的一个引脚,只能表示两个状态,IC的这个特性决定计算机的信息数据只能用二进制数来处理

所以二进制的进制方式就变成了逢二进一:
1,10,11,100……

二进制数不是专门为IC所设计的,但和IC的特性非常吻合

位:计算机处理信息的最小单位 = 二进制中的一位 = 1bit
bit 是二进制数位(binary digit)缩写
IC的一个引脚表示二进制数的一位

字节:基本单位
8 bit = 1 bite(“咬下的一口”)读音相似,因此bite被视为信息的基本单位

计算机内部所有信息都用二进制数处理,具体进行何种处理,取决于程序的编写方式

2.2 什么是二进制数

**的##次幂 = 位权
** = 基数(数值的表示方法进位计数知道中各位数上可能有的数值的个数)

2.3 移位运算和乘除运算的关系

移位运算:将二进制数值的各数位进行左右移动的运算

和十进制数一样,四则运算也可以使用在二进制数中,只要注意逢二进位即可

移位运算 可代替乘除法运算

2.4 便于计算机处理的”补数“

符号位;

求一个负数的正数表示方法,即求相应正数的补数,用补数来代表负数进行存储和运算

补数求解的变换方法:全部取反 +1

人为规定的编程语言中,eg整数数据类型,有的可以处理负数,有的则不能,即最高位为一的二进制数据中,不一定表示负数,要看认为规定的这个数是否可以处理负数,若不可以处理负数,则最高位不表示符号位,就看做数值位,若可以处理负数,则相反。

根据人为规定的是否可以处理负数,其能表示的值的范围也不同,即使两个数据类型能表示的值的数量相同(划分多少的字节给你存这个类型的变量,这个类型的变量总共能存多少个。)

能处理负数的数据类型的值的取值范围中,其表示的负数比正数多一 eg: -32768~32767

2个字节 16位二进制数,共能表示65536种值,若数据类型能够处理负数,则正数与负数一半一半是32768,最高位为符号位,不表示数值,则正数能表示的最大数值是:2^0+2^1+……+2^14=323767,最小值是0,负数能表示的最大值为-1,最小值为-323768

2.5 逻辑右移和算数右移的区别

移位有两种
左移都补0
右移分情况

逻辑右移:在最高位补0(霓虹灯向右滚动),溢出低位舍弃(图形模式
算数右移:在带符号的数值进行运算中,移位后要在最高位填充移位前符号位的值(0或1)

右移2位,变为原数的1/4倍
左 2 4

符号扩充:在保持值不变的前提下将其转换为16位和32位的二进制数;

不管是正数还是补数表示的负数,都只需用符号位的值(0或1)填充高位即可。

2.6 掌握逻辑运算的窍门

在运算中,与逻辑相对的术语是算数

算术:二进制表示的信息作为四则运算的数值来处理
逻辑:像图形模式那样,将数值处理为单纯的0和1的罗列

计算机能处理的运算,大体分为两类,
1)算术运算:之加减乘除四则运算
2)逻辑运算:只对二进制各数字位的0 和1 分别进行处理的运算,有
逻辑非—NOT运算
逻辑与—AND
逻辑或—OR
逻辑异或—XOR

第三章 计算机进行小数运算时出错的原因

热身回答

将小数分为符号、尾数、基数、指数4部分进行表现的形式称为浮点数(浮点数形式)

通过把0作为数值范围的中间值,从而在不使用符号位的情况下来表示负数的方法称为EXCESS系统表现

3.1 将0.1累加100次也得不到1

计算机在运算时为什么会出错,如何避免出错

3.2 用二进制数表示小数

进制之间的转换

3.3 计算机运算出错的原因

有一些十进制数的小数无法转换成二进制数,eg 十进制数 0.1 无法用二进制数正确表示,计算机这个功能有限的机器设备,是无法处理无限循环小数的。在遇到循环小数时,计算机就会根据变量数据类型所对应的长度将数值从中间截断或者四舍五入,所以 计算机计算3*(1/3)时会得到 0.999999(假如在0.333333时截断).所以计算机运算会出错。

3.4 什么是浮点数

双精度浮点数:用64位来表示全体小数(在c语言中 ;double)
单精度浮点数: 32 (float)
浮点数与定点数相对(小数点的实际位置固定不变

浮点数 = 符号 +尾数 +基数 + 指数 (基数为二,默认)

数据正负;符号部分:指使用一个数据位来表示数值的符号
数据大小;尾数+指数

为了方便计算机处理,需要制定一个统一的规则——正则表达式,可以将表现形式多样的浮点数统一为一种表现形式(浮点数可以用多种不同的形式来表示同一值。)

尾数部分 使用的是——将小数点前面的值固定为1的正则表达式(按照特定的规则来表示数据的形式。出小数点外,字符串以及数据库等,都有各自的正则表达式)

指数部分 使用的是——EXCESS 系统表现(为了表示负数时不使用符号位),通过将指数部分表示范围的中间值设为0,使得负数不需要用符号来表示

3.7 如何避免计算机计算出错

1)无视(不影响程序)

2)把小数转换成整数进行计算

3)BCD也是一种使用二进制表示十进制的方法

3.8 二进制数与十六进制数

在C语言中,在数值的开头加上 ‘ 0x ’ 就可以表示十六进制数;

实际程序中,二进制位数过多,看起来不方便,因此经常会用十六进制数来代替二进制数

第四章 熟练使用有棱有角的内存

热身回答
高级编程语言中的数据类型表示的是什么
占据内存区域的大小和存储在该内存区域的数据类型
eg c语言数据类型中的short类型。表示的是占据2字节的内存区域,并且存储整数

32位内存地址的环境中,指针变量的长度是32位
指针——用于存储内存地址的变量
用LIFO 方式进行数据读写的数据结构称为栈
栈,是一种后入先出(LIFO = Last in First out)式的数据结构

根据数据的大小链表分叉成两个方向的数据结构称为 二叉查找树
二叉查找树 ,从节点分成两个叉的树状数据结构

4.1 内存的物理机制很简单

内存IC 中有电源、地址信号、数据信号、控制信号等用于输入输出的大量引脚,通过为其指定地址,来进行数据的读写。 内存IC内部有大量可以存储8位数据的地方,通过地址指定这些场所,之后即可进行数据的读写

4.2 内存的逻辑模型是楼房

每层都存储数据——数据引脚的多少决定了计算机一次能够处理的数据的长度,即每层楼房可以存储的数据的位数,以此为单位来对数据进行处理

编程语言中的数据类型表示存储的是何种类型的数据。
在内存中——占用内存大小(楼层数)

即使是物理上以1个字节为单位来逐一读写数据的内存,在程序中,通过指定其类型(变量的数据类型等),也能实现以特定字节数位单位来进行读写

通过使用变量,即便不指定物理地址,也可以在程序中对内存进行读写,这是因为在程序运行时,Windows等操作系统会自动决定变量的物理地址

数据在内存中存储有两种方式
低字节序,将多字节数据的低位字节存储在内存低位地址的方式
高字节序, 高

4.3简单的指针

指针也是一种变量,它所表示的不是数据的值,而是存储着数据的内存地址,
指针变量的长度即内存地址的位数
通过使用指针,就可以对任意指定地址的数据进行读写

指针的数据类型表示一次可以读写的长度

4.4数组是高效使用内存的基础

数组:多个同样数据类型的数据在内存中连续排列的形式
索引,区分数组元素的各个数据
指定索引,即可对该索引所对应地址的内存进行读写操作(编译器完成索引和内存的变换工作)
数组的定义中所指定的数据类型,也表示一次能够读写的内存大小,这样就可以多个字节来进行读写,简化程序所以可以指定任意数据类型来定义数组

数组和内存的物理构造是一样的——数组是内存的使用方法的基础

4.5栈、队列以及环形缓冲区

内存的使用,数组的变形方法
每次保存临时数据需要指定地址和索引,程序麻烦——改进——栈和队列——都可以不通过指定地址和索引对数组的元素进行读写
区别,数据出入顺序不同

对内存数据进行读写时——
栈,LIFO(Last input first out )(干草堆,堆在最上面的最先拿走——通过Push Pop 函数实现写入和读出数据)
队列,FIFO (First input first out)(排队买票,排在最前面的最先拿票,最先走出队列——通过Enqueue DeQueue 函数实现写入和读出数据)——能够协调好数据输入和处理时间的关系——一般以环状缓冲区的方式来实现——连接数组的开头和结尾——数据写入和读出实现循环

4.6 链表使元素的追加和删除更加容易

否则删除或者添加一个数据,底下其余 所有的数据地址都要改变,使计算机速度变慢

4.7 二叉查找树使数据搜索更有效

二叉查找数是指在链表的基础上往数组中追加元素时,考虑到数据的大小关系,将其分成左右两个方向的表现形式

第五章 内存和磁盘的亲密关系

存储程序方式(程序内置方式)指的是什么
在存储装置中保存程序,通过有序地被读出来并逐一执行的方式

通过使用内存来提高磁盘访问速度的机制称为——Disk Cache(磁盘缓存),磁盘缓存是指,把磁盘中读出的数据存储在内存中,当该数据再次被读取时,不是从磁盘而是直接从内存中高速读出

把磁盘的一部分作为假象内存来使用的机制称为——虚拟内存(virtual memory),借助虚拟内存,哪怕是内存容量不足的计算机,也可以运行很大的程序

Windows中,在程序运行时,存储着可以动态加载调用的函数和数据的文件称为——DLL(Dynamic Link Library)

在EXE程序文件中,静态加载函数的方式称为——静态链接,函数的加载方式有静态链接和动态链接两种

在Windows计算机中,一般磁盘的1个扇区时 512 个字节,扇区是磁盘保存数据的物理单位

从存储容量上看,内存高速低价 ,磁盘低速廉价

5.1 不读入内存就无法运行

程序要从磁盘加载到内存后才开始运行

5.2 磁盘缓存加快了磁盘访问速度

缓存( cache)高速缓存、仓库
磁盘缓存——把从磁盘中读出的数据存储到内存空间中的方式,
当需要读取同一数据时,就不用通过实际的磁盘,而是从磁盘缓存中把内容读出
可大 大改善磁盘数据的访问数据

但随着硬盘访问速度的大幅改善,磁盘缓存的效果没有之前那么明显了

5.3 虚拟内存把磁盘作为部分内存来使用

虚拟内存 ——把磁盘的一部分作为假象的内存来使用
虚拟内存的方法有,分页式和分段式两种,

Windows采用的是分页式,在不考虑程序构造的情况下,把运行的程序按照一定大小的页进行分割,并以页为单位在内存和磁盘间进行置换,Windows计算机页的大小是4KB ,磁盘内容读出到内存——Page In ;内存内容写入磁盘——Page Out ,
虚拟内存用的文件——page file ,文件大小就是虚拟内存的大小
在Windows的控制面板中,可查看或变更当前虚拟内存的设定

分段式虚拟内存,把要运行的程序分割成以处理集合及数据集合等为单位的段落,然后再以分割后的段落为单位在内存和磁盘之间进行数据置换

5.4节约内存的编程方法

图形用户界面——GUI
Windows前身 MS-DOS 操作系统——CLI(命令行界面)

Page In 和Page Out 往往伴随低速的磁盘访问,所以虚拟内存无法彻底解决内存不足的问题
两种方法,增加内存容量和把要运行的应用文件变小

两个把应用文件变小的编程方法
(1)通过DLL文件实现函数共有
DLL(Dynamic Link Library )文件,在程序运行时可以动态加载Library(函数和数据集合)的文件,多个应用可以共有同一个DLL文件,达到节约内存的效果,而原本的静态链接则会导致内存的利用效率下降,进行动态链接则可以节省内存
(2)通过调用_stdcall来减小程序文件的大小
_stdcall ——standard call(标准调用),Windows提供的DLL文件内的函数,基本上都是_stdcall 调用方式。主要是为了节约内存。

C语言中,在调用函数后,需要进行栈清理处理指令,(把不需要的数据和传递函数的参数时使用的内存上的栈区域中清理出去)
C语言通过栈来传递函数的参数,32位的CPU中,一次push指令可以存储4个字节的数据

CPU会提前准备好栈机制,往栈中存储数据的汇编语言指令是 Push;从栈中取出数据的汇编语言指令是pop 。栈一般是用来实现函数调用机制的。如果想任意利用栈,程序员就需要自己用程序来实现所需要的栈机制。
CPU中,栈中堆积的最高的数据地址是保存在esp(esp是Pentium系列CPU的栈指针名)中,

C语言中,函数的返回值,是通过寄存器而非栈来返回的

5.5 磁盘的物理结构

磁盘的物理结构是指 磁盘存储数据的形式
磁盘是通过把其物理表面划分成多个空间来使用的。
划分的方式为
扇区方式 ——磁盘划分为固定长度的空间
可变长方式 两种——磁盘划分为可变的空间

扇区是对磁盘进行物理读写的最小单位,
Windows中,一般1个扇区 = 512字节
但在逻辑方面(软件方面)对磁盘进行读写的单位是扇区整数倍簇,根据磁盘容量不同,一簇可以是多个扇区。磁盘容量越大,簇的容量就越大,但在软盘中,1簇 = 512字节 = 1扇区,此时簇和扇区的大小是相等的

不管是硬盘还是软盘,不同的文件是不能存储在同一个簇中的——所以无论多小的文件,都会占用1簇的空间,所以,所有的文件都会占用1簇的整数倍的磁盘空间。

(注:本篇笔记是根据《程序是怎样跑起来的》一书进行的章节规划,想细致深入了解的小伙伴就去看看这本书吧~)


文章作者: meimiss
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 meimiss !
评论
  目录