这个专题的所有学习笔记来自于对武汉大学计算机学院软件工程专业大三上学期的专业必修课《系统级程序设计》的学习(教材为深入理解计算机系统CSAPP),涉及的编程语言全部为C语言和C++语言。
该博客为第3单元的学习笔记,这一单元的主要内容是信息存储、整数的表示和运算、浮点数的表示,内容来自《深入理解计算机系统》这本书的第2章,对应ssd6课程的lecture4。
这一单元的学习笔记主要起到提纲挈领的作用,想要真正学习到具体内容还是要看书,认真做书上的练习题。
信息存储
我们研究三种最重要的数字表示。无符号编码基于传统的二进制表示法,表示大于或者等于零的数字,补码编码是表示有符号整数的最常见的方式(有符号整数就是可以为正或者为负的数字),浮点数编码是表示实数的科学计数法的以2为基数的版本。
计算机的表示法是用有限数量的位来对一个数字编码,因此当结果太大以至不能表示时,某些运算就会溢出。
大多数计算机使用8位的块,或者字节,作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存。内存的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能地址的集合就称为虚拟地址空间。
C语言中一个指针的值(无论它指向一个整数、一个结构或者某个其他程序对象)都是某个存储块的第一个字节的虚拟地址。
(1)十六进制表示法
完成十六进制、十进制、二进制之间的相互转换
(2)字数据大小
每台计算机都有一个字长,指明指针数据的标称大小。对于一个字长为w的机器而言,虚拟地址的范围为0——
2w
2
w
-1,程序最多访问
2w
2
w
个字节。
(3)寻址和字节顺序
最低有效字节在最前面的方式称为小端法,最高有效字节在最前面的方式称为大端法。(练习题5和6)
(4)表示字符串
(5)表示代码
(6)布尔代数简介
(7)C语言中的位级运算
使用异或交换指针变量存储的值(练习题10和练习题11)
掩码运算(练习题12)
练习题13
(8)C语言中的逻辑运算
注意位级运算和逻辑运算的区别(练习题14)
简单的运用(练习题15)
(9)C语言中的移位运算
x
<<
<<
<script id="MathJax-Element-34" type="math/tex"><<</script>k表示左移运算,x向左移动k位,丢弃最高的k位,并在右端补k个0
x
>>
>>
k表示右移运算,x向右移动k位,丢弃最低的k位,并在左端补k个0(逻辑右移)或者x向右移动k位,丢弃最低的k位,并在左端补k个最高有效位的值(算术右移)
练习题16
整数表示
(1)整型数据类型
(2)无符号数的编码
B2Uw
B
2
U
w
(w表示整数数据类型的位数)
比如
B2U4
B
2
U
4
([1011])=11
(3)补码编码
B2Tw
B
2
T
w
比如
B2T4
B
2
T
4
([1011])=-1*8+0*4+1*2+1*1=-5
(4)有符号数和无符号数之间的转换
P50公式2.5
(5)C语言中的有符号数和无符号数
当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地将有符号参数强制类型转换为无符号数,并假设这两个数都是非负的,来执行这个运算。
(6)扩展一个数字的位表示
一个常见的运算是在不同字长的整数之间转换,同时保持数值不变。
要将一个无符号数转换为一个更大的数据类型,我们只要简单地在表示的开头添加0,这种运算被称为零扩展。
对于无符号表示,进行零扩展,
对于补码表示,进行符号扩展。
举例:(练习题24)假设将一个四位数值(用十六进制数字0-F表示)截断到一个3位数值(用十六进制数字0-7表示),考虑对下列位模式的无符号和补码解释的截断结果:
(7) 截断数字
对于无符号数和补码数字的截断结果。
练习题24
十六进制 | 无符号表示 | 补码表示 | |||
原始值 | 截断值 | 原始值 | 截断值 | 原始值 | 截断值 |
0 | 0 | 0 | 0 | 0 | 0 |
2 | 2 | 2 | 2 | 2 | 2 |
9 | 1 | 9 | 1 | -7 | 1 |
B | 3 | 11 | 3 | -5 | 3 |
F | 7 | 15 | 7 | -1 | -1 |
根据上述公式,对于无符号表示,截断的影响是相当直观的。结果就是他们模8(这里w=4,k=3,模2的k次方)的余数
对于补码表示,首先计算这个参数模8的余数,然后对于这些余数应用函数
U2T3
U
2
T
3
。例如原始值是-7的情况,首先计算出余数是1,再对1应用
U2T3
U
2
T
3
,即把001从无符号数转为补码,得到的结果还是1。
再例如原始值是-1的情况,余数是7,对7应用
U2T3
U
2
T
3
,把7(111)从无符号数转为补码,得到的结果是-1。
(8)关于有符号数与无符号数的建议
练习题25与练习题26,无符号数错误使用的例子.
整数运算
(1)无符号加法
无符号数加法(正常和溢出两类情况)、检测无符号数加法中的溢出(和比加数小)、无符号数求反(等于0和大于0两类情况).
(2)补码加法
补码加法(正溢出、正常、负溢出)
检测补码加法中的溢出(当且仅当两个加数都>0而和≤0时发生了正溢出,当且仅当两个加数都<0而和≥0时发生了负溢出)
(3)补码的非
等于
TMINw
T
M
I
N
w
和大于
TMINw
T
M
I
N
w
两类情况
(4)无符号乘法
(5)补码乘法
(6)乘以常数
移位运算(左移)
(7)除以2的幂
除以2的幂的无符号除法,向下舍入一个正值
除以2的幂的补码除法,如果被除数小于0而除数大于0,结果向上舍入一个负值,为了实现向上舍入,在移位之前加上一个偏量。
练习题42.在不使用任何测试或条件运算的情况下计算偏量。由于是右移4位,偏量应为0000(为正,向下舍入)或者1111(为负,通过偏量实现向上舍入),使用右移31位并通过掩码屏蔽掉适当的位的方法得到偏量
练习题43是一道很简单,但很有意思的题。两段代码完成的是同样的事情,通过其中一段代码推测出另外一段代码的相关参数。
(8)关于整数运算的最后思考
练习题44,非常经典的题目,要仔细看,对于很多概念的理解很有帮助。
浮点数
(1)二进制小数
(2)IEEE浮点表示
符号、尾数和阶码。注意三种情况:规格化的值、非规格化的值、特殊值。
(3)数字示例
PPT中的两个例子规格化的情况
练习把一些整数值转化成浮点形式对理解浮点表示很有用:
P82页下面的例子,以及练习题48
浮点数不能准确描述的最小正整数:练习题49
(4)舍入
练习题50和练习题52
(5)浮点运算
(6)C语言中的浮点数
练习题54(很重要,好好看一下)