20145320《信息安全系统设计基础》第3周学习总结
教材学习内容总结
-
P20
-
无符号编码基于传统的二进制表示法,表示大于或者等于零的数字。
-
补码编码是表示有符号整数的最常见的方式,有符号整数就是可以为正或者为负的数字。
-
浮点数编码是表示实数的科学记数法的以二为基数的版本。
-
由于溢出使得一个正整数会变成负整数,因此会出现逆向漏洞。
-
-
P22进制转换
-
十六进制表示法,十进制、二进制和十六进制表示之间进行转换
-
C语言中以0x开头表示16进制的数,每个16进制的数对应四位二进制的数。
-
-
p25: gcc -m32 可以在64位机上(比如实验楼的环境)生成32位的代码
-
p26: 字节顺序是网络编程的基础,记住小端是“高对高、低对低”,大端与之相反就可以了。
-
小端法:从最低有效字节到最高有效字节的顺序存储对象
-
大端法:最高有效字节在最前面的方法。
-
-
强制类型转换(cast)来允许以一种数据类型引用一个对象,而这种数据类型与创建这个对象时定义的数据类型不同。大多数应用编程都强烈不推荐这种编码技巧,但是它们对系统级编程来说是非常有用,甚至是必需的
-
表示字符串
-
C语言中字符串被编码为一个以null(其值为0)字符结尾的字符数组。每个字符都由某个标准编码来表示,最常见的是ASCII字符码。
-
ASCII字符集适合于编码英语文档,但是在表达一些特殊字符方面却没有太多办法,它完全不适合编码希腊语、俄语和中文这样语言的文档。近几年 ,开发出很多方法来对不同语言的文字编码。Java编程语言使用Unicode来表示字符串。对于C语言也有支持Unicode的程序库。
-
-
p32:
- 能区分逻辑运算(结果是1或0)和位运算(结果是位向量),所有逻辑运算都可以用与、或、非表达(最大式、最小式),而与或非可以用“与非”或“或非”表达,所以,只要一个与非门,就可以完成所有的逻辑运算。
-
p33: 掩码是位运算的重要应用,对特定位可以置一,可以清零
-
某一位置为一,表示信号i有效,0则为信号i是被屏蔽的。
-
位级运算的一个常见用法就是实现掩码运算,这里掩码是一个位模式,表示从一个字中选出的位的集合。让我们来看一个例子,掩码0xFF(最低的8位为1)表示一个字的低位字节。位级运算x&0xFF生成一个由x的最低有效字节组成的值,而其他的字节就被置为0。比如,对于x=0x89ABCDEF,其表达式将得到0x000000EF。表达式~0将生成一个全1的掩码,不管机器的字大小是多少。尽管对于一个32位机器来说,同样的掩码可以写成0xFFFFFFFF,但是这样的代码不是可移植的。
-
-
p39:
- 补码的利用寄存器的长度是固定的特性简化数学运算。想想钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。
-
p44: 注意C语言中有符号数和无符号数的转换规则,位向量不变。想想第一章说的 信息就是“位+上下文”
-
有符号数和无符号数之间的转换
-
将函数U2Tw定义为U2Tw(x) = 4B2Tw(U2Bw(x))。这个函数的输入是一个0~2w - 1之间的数,结果得到一个-2w-1~2w-1-1之间的值,这里两个数有相同的位模式,除了参数是无符号的,而结果是以补码表示的。类似地,对于-2w-1~2w-1-1之间的值x,函数T2Uw定义为 T2Uw(x) = 4 B2Uw(T2Bw(x)),生成一个数的无符号表示和x的补码表示相同
-
-
p48: 怎么样让负数等于正数? 信息安全的逆向思维
-
当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地将有符号参数强制类型转换为无符号数,并假设这两个数都是非负的,来执行这个运算。
-
第二个是无符号运算的话,第一个也会被隐式地转换为无符号数。这样负数变成了无符号的正数。
-
-
p49: 0扩展和符号扩展
-
将一个无符号数转换为一个更大的数据类型,我们只需要简单地在表示的开头添加0,这种运算称为零扩展。
-
将一个补码数字转换为一个更大的数据类型可以执行符号扩展,规则是在表示中添加最高有效位的值。
-
-
p54: 如何让整数运算溢出?如何避免?
-
p67: 关于整数运算的最后思考
-
p67: 浮点数有科学计数法的基础就不难理解,IEEE标准754
-
p70: IEEE浮点标准,float/double类型
-
IEEE浮点标准用V = (-1)^s × M × 2^E的形式来表示一个数:
-
符号(sign) s决定这个数是负数(s=1)还是正数(s=0),而对于数值0的符号位解释作为特殊情况处理。
-
尾数(significand) M是一个二进制小数,它的范围是1~2-ε,或者是0~1-ε。• 阶码(exponent) E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。将浮点数的位表示划分为三个字段,分别对这些值进行编码:
-
一个单独的符号位s直接编码符号s。
-
k位的阶码字段exp = ek-1…e1e0编码阶码E。
-
n位小数字段frac = fn-1…f1 f0编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。
-
-
三种情况:
-
情况1:规格化的值
-
情况2:非规格化的值
-
情况3:特殊值
-
-
-
p68: 浮点数运算的不精确性与舍入
-
舍入:向偶数舍入,向零舍入,向下舍入,向上舍入。
-
浮点运算:把浮点值x和y看成实数,而某个运算⊙定义在实数上,计算将产生Round (x ⊙ y),这是对实际运算的精确结果进行舍入后的结果。在实际中,浮点单元的设计者使用一些聪明的小技巧来避免执行这种精确的计算,因为计算只要精确到能够保证得到一个正确的舍入结果就可以了。当参数中有一个是特殊值(如-0、-∞或NaN)时,IEEE标准定义了一些使之更合理的规则。例如,定义1/-0将产生-∞,而定义1/+0会产生+∞。
-
-
p74: 整数与浮点数表示同一个数字的关系
-
p78: 整数与浮点数转换规则
教材学习中的问题和解决过程
P28页代码问题
- 有些同学问我为什么输入P28页的代码之后会通不过编译,然后加上P30的代码还是不行。就像下面一样。
- 这是因为没有主函数,P28以及P30页的代码都是以子函数的形式提供,没有主函数程序找不到入口。所以我们要自己改编一下P30的代码,让他变成一个主函数。其子函数输入的形参我们要变成自己输入的实参。
- 这个程序干的是使用强制类型转换来访问和打印不同程序对象的字节表示,之所以输出16进制,是因为“%.2x”中的x控制的。
p35 练习2.11
- 发现输入个数为奇数时,中间为0
-
这是因为当数目为奇数时,会出现first==last的情况,这时调用
inplace_swap
函数里面的*y = x^y语句时相当于自己异或自己,就会出现0的情况。 -
解决方法就是把first<=last改成first<last。
P44关于有无符号数之间转换
- 强制类型转换的结果保持位值不变,只是改变解释的方式
- 可以看到16位补码的-12345与53191的16位无符号表示一样。32位无符号4294967295和-1的补码形式一样。