2016.10.15 - 10.25
《程序是怎样跑起来的》1-6章
- 矢泽久雄 / 著
- 李俊峰 / 译
个人学习笔记。
10.15
1 对程序员来说CPU是什么
0 问题 & 重点
1. 程序是什么?
[1] 存储在内存中的高低电平序列。
[2] 指示计算机每一步动作的一组指令。
2. 程序是由什么组成的?
[1] 高低电平序列[有的序列对应数据;有的序列对应指令]。
[2] 指令和数据。
3. 什么是机器语言?
[1] 输入CPU后能让CPU产生相应高低电平输出的高低电平序列所组成的集合。[高低电平序列被逻辑的10序列来抽象表示,10序列再被助记符来对应表示]
[2] CPU可以直接识别并使用的语言。
4. 正在运行的程序存储在什么位置?
[1] 内存或cahe。
[2] 内存。
5. 什么是内存地址?
[1] 通过它输入给地址译码器后可以访问到一块内存的逻辑编号。
[2] 用来表示指令和数据存储在内存中位置的数值。
6. 计算机的构成元件中,负责程序的解释和运行的是哪个?
[1] 控制器。
[2] CPU。
需要按照问题所在层次回答问题。
重点。程序员需要了解CPU是如何运行的,特别是要弄清楚负责保存指令和数据的寄存器的机制。
1.1 CPU的内部结构解析
寄存器是程序员需要了解的。剩余部分不需要太过于关注。机器语言级别的程序是通过操作寄存器来描述功能的。
1.2 CPU是寄存器的集合体
程序计数器。程序计数器寄存器的值是内存地址,CPU会将程序计数器内的值(内存地址)中的内容取出来放到相应寄存器中(指令、数据、地址)。汇编指令中有很多指令都能够更改程序计数器的值(从C语言层面来讲,是分支和循环;从汇编语言层面讲,是转移指令),程序计数器的值决定程序执行流程。
标志寄存器。一些汇编指令执行后还会更改标志寄存器某些位的值。也有一些依赖于标志寄存器某些位作为条件的汇编指令。(这些指令运算后的某个输出与该寄存器的某个位相连接)
10.16
1.5 函数调用机制
[1] 先插入点其它的话题 —— 关于程序被编译链接成的区域。
/* main.c
* 调用stack.c中的函数,
* 查看程序的指令区、数据区、栈区以及函数被调用时的栈帧
* 2016.10.16
*/
/* global variable*/
double fv = 0.1f;
/* declare function defined in stack.c */
void push(double f);
double pop(void);
int main(void)
{
push(fv);
fv = pop();
return 0;
}
/* stack.c
* 定义一个数组以栈的机制使用它
* routine form 《TCPL》Section 4.3, modified a little by me
* 2016.10.16
*/
#define MAXVAL 100 /* maximum depth of val stack */
static int sp = 0; /* next free stack position */
static double val[MAXVAL]; /* value stack */
/* push: push f onto value stack */
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
return;
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else
return 0.0;
}
截取segment中关于代码段和数据段的信息:
然后在segment所在文件中搜索main、push、pop三个函数(如/main):
.text段的(虚拟)地址范围为0x08048300 ~ 0x080484fc。再查看这三个函数的(虚拟)地址,pop为0x08048418,push为0x080483e0,main为0x080483b4。它们的内容都在.text段中。
.data段的(虚拟)地址范围为0x0804a008 ~ 0x0804a018,再查看全局变量fv的虚拟地址:
.bss段的(虚拟)地址范围为0x0804a020 ~ 0x0804a380,两个静态全局变量的(虚拟)地址为:
[2] 函数调用机制
[整张图不清晰,将各部分分解如下]
10.17
1.6 CPU处理指令的类型
2 数据是用二进制数表示的
0 问题 & 重点
1. 32位是几个字节?
4。
2. 二进制数01011100转换成十进制数是多少?
92。
3. 二进制数00001111左移两位后,会变成原数的几倍?
4。
4. 补码形式表示的8位二进制数11111111,用十进制数表示的话是多少?
无符号数255;有符号数-1。
5.补码形式表示的8位二进制数10101010,用16位二进制数表示的话是多少?
66.[理解错了]
1111111110101010
6. 反转部分图形模式时,使用的是什么逻辑运算?
[2] XOR。
重点。为什么计算机处理的信息要用二进制数来表示呢?
2.1 用二进制数表示计算机信息的原因
2.2 什么是二进制数
2.4 便于计算机处理的“补数”
10.18
2.5 逻辑右移和算术右移的区别
2.6 掌握逻辑运算的窍门
逻辑运算是指对二进制数各数字位的0和1分别进行处理的运算。
3 计算机进行小数运算时出错的原因
0 问题 & 重点
1. 二进制数0.1,用十进制数表示的话是多少?
0.5。
2. 用小数点后有3位的二进制数,能表示十进制数0.625吗?
可以。
3. 将小数分为符号、尾数、基数、指数4部分进行表现的形式称为什么?
[1] 科学计数法。
[2] 浮点数。
4. 二进制的基数是多少?
2.
5. 通过把0作为数值范围的中间值,从而在不使用符号位的情况下来表示负数的表示方法称为什么?
[2] EXCESS系统表现。
6. 10101100.01010011这个二进制数,用十六进制数表示的话是多少?
0xac.53。
重点。计算机进行小数处理的机制。
3.1 将0.1累加到100次也得不到10
3.4 什么是浮点数
浮点数是指用符号、尾数、基数(二进制为2)和指数这四部分来表示的小数。[像 0.12345x103 和 0.12345x10−1 这样使用与实际小数点位置不同的书写方法来表示小数的形式称为浮点数。与浮点数相对的是定点数,使用定点数表示小数时,小数点的实际位置固定不变。如 0.12345x103 和 0.12345x10−1 用定点数来表示的话即为123.45和0.012345]
10.19
3.7 如何避免计算机计算出错
无视错误。根据程序目的的不同,有时一些微小的偏差并不会造成什么问题。例如,假设使用计算机设计工业制品。将100个长0.1mm的零件连接起来后,其长度并非一定要是10mm,10.000002mm也没有任何问题。
将小数换成整数来计算,然后再倍数回小数。
4 熟练使用有棱有角的内存
0 问题 & 重点
1. 有十个地址信号引脚的内存IC(集成电路)可以指定的地址范围是多少?
0 ~
210−1
2. 高级编程语言中的数据类型表示的是什么?
[1] 占用内存的大小。
[2] 占用内存的大小和存储在该内存区域的数据类型。
3. 在32位内存地址的环境中,指针变量的长度是多少位?
32位。
4. 与物理内存有着相同构造的数组的数据类型长度是多少?
[1] 没看懂。
[2] 1字节。
5. 用LIFO方式进行数据读写的数据结构称为什么?
栈。
6. 根据数据的大小链表分叉成两个方向的数据结构称为什么?
[1] 二叉树。
[2] 二叉查找树。
重点。只要在程序上花一些心思,就可以将内存变成各种各样的数据结构来使用。
4.1 内存的物理机制和内存的逻辑模型
10.20
4.3 简单的指针
10.22
指针的理解:变量 +类型。
4.4 数组是高效使用内存的基础
5 内存和磁盘的亲密关系
0 问题 & 重点
10.24
1. 存储程序方式指的是什么?
[1] 问题何意。
[2] 在存储装置中保存程序,并逐一运行的方式。
2. 通过使用内存来提高磁盘访问速度的机制称为什么?
磁盘缓存机制。
3. 把磁盘的一部分作为假想内存来使用的机制称为什么?
虚拟内存。
4. Windows中,在程序运行时,存储着可以动态加载调用的函数和数据的文件称为什么?
动态链接文件。
5. 在EXE程序文件中,静态加载函数的方式称为什么?
静态链接。
6. 在Windows计算机中,一般磁盘的1个扇区是多少字节。
512字节。
重点。内存和磁盘的亲密关系。
5.1 不读入内存就无法运行
存储程序方式机制是指程序保存在存储设备中,通过有序地读出来实现运行。
因为负责解析和运行程序-的CPU是通过程序计数器来指定内存地址,然后才能读取程序。所以在磁盘中保存的原始程序是无法直接运行的,必须加载到内存中才能运行。[即使CPU可以用程序计数器指定磁盘地址并可直接读取磁盘中保存的程序,由于磁盘读取速度较慢,程序的运行速度还是会降低。]
5.2 磁盘缓存加快了磁盘访问速度
磁盘缓存指的是把磁盘中读出的数据存储到内存空间中的方式。这样一来,当接下来需要读取同一数据时,就不用通过实际的磁盘,而是从磁盘缓存中把内容读出。使用磁盘缓存可以大大改善磁盘数据的访问速度。
[随着硬盘访问速度的大幅度改善,磁盘缓存的效果也没有之前那么明显了。这种缓存的机制在其他情况下也会遇到。如在Web浏览器中,Web浏览器是通过网络来获取远程Web服务器的数据并将其显示出来的。在显示较大图片等文件时,会花费不少时间。于是,Web浏览器就可以把获取的数据暂时保存在磁盘中,然后在需要时再显示磁盘中的数据]
5.3 虚拟内存把磁盘作为部分内存来使用
虚拟内存是指把磁盘的一部分作为假想的内存来使用。[这与磁盘缓存是假想的磁盘(实际上是内存)相对,虚拟内存是假想的内存(实际上是磁盘)]
分页式虚拟内存。不考虑程序构造,把运行的程序按照一定大小的页进行分割,并以页为单位在内存和磁盘间进行置换。[一般情况下,Windows计算机的页大小是4KB。也就是说,把大程序用4KB的页来进行划分,并以页为单位放入磁盘(虚拟内存)或内存中。为了实现虚拟内存功能,Windows在磁盘上提供了虚拟内存用的文件(page file,页文件)。该文件由Windows自动做成和管理。文件的大小也就是虚拟内存的大小,通常是实际内存的相同程度至两倍程度]
分段式虚拟内存。把要运行的程序分割成以处理集合及数据集合等为单位的段落,然后再以分割后的段落为单位在内存和磁盘之间进行数据置换。
5.4 节约内存的编程方法
虚拟内存无法彻底解决内存不足问题。[page in、page out携带的低速访问等]
栈清理处理指把不再需要的数据 从接收和传递 函数的参数时使用的内存上的栈区域中清理出去(即清理形参所占用的空间)。该命令不是程序记述的,而是在程序编译时由编译器自动附加到程序中的。编译器默认将该处理附加在函数调用方。
5.5 磁盘的物理结构
扇区是(BIOS)对磁盘进行物理读写的最小单位。簇是Windows在逻辑方面(软件方面)对磁盘进行读写的单位,它是扇区的整数倍。windows中的文件以簇为单位进行存储。扇区和簇的大小,是由处理速度和存储容量的平衡来决定的。
如果跳出BIOS或Windows,只要掌握磁盘读写原理,随汝怎么样规划磁盘读写方式。
6 亲自尝试压缩数据
0 问题 & 重点
10.25
1. 文件储存的基本单位是什么?
1字节。
2. DOC、LZH和TXT这些扩展名中,哪一个是压缩文件的扩展名?
LZH。
3. 文件内容用“数据的值 x 循环次数”来表示的压缩方法是RLE算法还是哈夫曼算法?
RLE。
4. 在Windows计算机经常使用SHIFT JIS字符编码中,1个半角英数是用几个字节的数据来表示的?
1字节。
5. BMP(BITMAP)格式的图像文件,是压缩过的吗?
没有。
6. 可逆压缩和非可逆压缩的不同点是什么?
可逆压缩可解压;非可逆压缩不可解压(不可还原)或还原后会丢失一部分信息。
重点。为什么文件可以压缩。
6.1 文件以字节为单位保存
程序文件中存储数据的单位是字节。文字、颜色等都有对应的编码。[单位也是基于字节的]
6.2 RLE算法的机制
AAAAAABBCDDEEEEEF采用RLE(Run Length Encoding)方式压缩为A6B2C1D2E5F1。因为图像重复的相同字节比较多,所以RLE常用于压缩图像。但不太适合文本文件的压缩。但如果再在RLE算法的基础上下点功夫,如不以1个字符为单位,而以字符串为单位来查找重复次数,这样压缩的文件也能小一些。
6.4 通过莫尔斯编码来看哈夫曼算法的基础
哈夫曼算法抛弃了半角英文数字的1个字符是1个字节的数据[虽然保存数据是以1字节为单位],即多次出现的字符用小于8位的字节数来表示[短编码],不常出现的字符则可以用超过8位的字节数来表示[长编码]。[采用不同位长的初衷是每个数字对应一个编码]
莫尔斯编码是根据日常文本中各字符出现频率来决定表示各字符的编码的数据长度的。哈夫曼为压缩对象文件构造最佳的编码体系[即在文中出现频率最高者采用短编码],并以该编码体系为基础来进行压缩。用哈夫曼算法压缩过的文件中,存储着哈夫曼编码信息和压缩过的数据。
[2016.11.01 - 10:21]