CMU 15-213|Overview & Bits Representation
冯诺依曼架构
组成部分
最经典的计算机架构,包含五个重要组成部分
- 存储器
- 控制器
- 运算器
- 输入
- 输出
现在的计算机也基本是基于这个架构的,只是运算器和控制器统一交由 CPU 来进行处理。
但是和冯诺依曼体系结构对应的当年还有一个叫做哈佛结构的:它和冯诺依曼架构最大的区别在于能够同时访问数据和指令,虽然哈佛结构很快就黯然退场了,但是如今在移动端市场流行的 ARM 架构也是由此演变而来。
设计缺陷
可以说如今计算机系统出现的诸多不稳定,是在冯诺依曼架构设计之初就注定的。
缓存溢出可以执行攻击者预订好的程序(游戏机设备的 jailbreak 有些就来自于此)
甚至采用 返回导向编程 的堆栈溢出攻击,在出现之后长达十多年里,主流操作系统都毫无防范之力
在 CSAPP 的实验中,我们将会亲自体验一番漏洞攻击,黑客模拟器XD
这门课程的必要性
程序的执行不仅仅是编写代码这么简单,代码写的好并不代表最终的执行就会正常。
我们对于一个事物的认知决定了如何更好的利用这个事物。
程序的执行除了代码本身,还需要结合内存,缓存,运算器等等部件,同时编译器,计算机系统的其他概念也会影响程序的最终执行,这门课程可以让我们从里到外的理解程序到底是如何执行的,这样才能写出更好更高效的代码。
数据的机器级表示
无符号和有符号
他们所能表示的数之间的关系可以直观的看下图:
这里其实有一种偏移 bias 的感觉,那就是如果讨论表示范围,对于同一个二进制的数据,有符号和无符号数据范围存在一定的 bias
目前主流的编程语言,默认都是有符号数,为了便于保存负数,但是 c 提供了无符号的声明形式
1 |
|
转换操作
无符号数和有符号数在计算机的底层硬件表示中都是二进制存在的,只是计算机针对我们理解的无符号和有符号,解释的方式不同
因此转换操作本身并不会改变二进制数据的实际内容,改变的只是计算机解释当前数值的方式
在进行互相转换的时候需注意:如果同时出现有符号和无符号的运算/比较,计算机在解释的时候会统一转化为无符号来进行解析
运算和溢出
无论是无符号数还是有符号数,一旦用来表示数值的最高位发生了进位/超出了表达形式/改变了符号位,就会发生溢出
无符号数溢出
实际上是 mod 操作,因为无符号本身并不需要牺牲一个 bit 的位置来表示符号,因此如果超出数据范围了,例如 3 bit 下, 110+111 = 6+7 = 13 = 1101 ,但是由于只能存储三位,因此实际存储的数据只有 101 因此最终结果实际上只有 13%8 = 5
有符号数溢出
分为正溢出和负溢出两种
还是以 3 bit 举例,对于有符号数能表示的范围应当是 -4 ~ 3,以 011+010 = 3+2 = 5 = 101,但是在二进制的解释下最终结果是 -4+1 =-3,这种情况就是正溢出(我们认为的5超出了能表示的范围,虽然 bit 位数没有超出,但是有符号数解释的最高位符号位收到了影响,溢出为了负数)
浮点数
浮点数的IEEE存储形式定义
规范化值
M默认心里有一个1,这个1不需要实际的编码位置,只需要默认心里记住