20145201 《信息安全系统设计基础》第3周学习总结

20145201 《信息安全系统设计基础》第3周学习总结

教材学习内容总结

三种最重要的数字表示:html

  • 无符号
  • 补码
  • 浮点数
    运算:linux

  • 整数运算
  • 浮点运算git

整数运算和浮点运算不一样:程序员

整数运算只能编码相对较小的范围,可是是精确的;编程

浮点运算能够编码一个较大的范围,可是是近似的;浮点运算不可结合。数组

注意:溢出——运算位数的限制安全

从逆向角度考虑为何会产生漏洞
大量计算机漏洞都是因为算数运算的微妙细节引起的。好比无符号数、有符号数、浮点数的局限性;无符号数或者有符号数的表示范围有限,而浮点数虽然编码范围大,可是不精确。函数

信息存储

1.十六进制表示法学习

经常使用进制:二进制(B),十进制(D),八进制(O或者Q),十六进制(H)编码

转换为二进制-十六进制相互转换,二进制的四位数字对应十六进制的一位数字。

同理,二进制与八进制的转化是三位对应一位。

tips:拿二进制做中间结果就好转了

当 n 表 示 成 i + 4 j 的 形 式 , 其 中 0 ≤ i ≤ 3 时 , 我 们 可 以 把 x 写 成 开 头 的 十 六 进 制 数 字 为 1( i = 0 )、2( i = 1 )、 4(i=2)或者 8(i=3)

2.字

字长决定虚拟地址空间的最大大小。字长为w,虚拟地址的范围为0~(2^w-1)

3.数据大小

gcc -m32 能够在64位机上生成32位的代码

4.寻址和字节顺序

1).小端法和大端法

小端法:最低有效字节在前面——“高对高,低对低”
大端法:最高有效字节在前面

2).强制类型转换

书28页代码

5.布尔代数

经常使用运算符号:

与: &
或: |
非: ~
异或:^

位向量

位向量:有固定长度为w、由0和1组成的串。
位向量的应用——表示有限集合。
布尔运算 | 和 & 分别对应于集合的并和交,而 ~ 对应于于集合的补。

6.位级运算

位运算:位向量按位进行逻辑运算,结果还是位向量(区别于逻辑运算)
常见用法:掩码——用来选择性的屏蔽信号

位级表达式
位级表达式的计算,要将经过转化为二进制表示进行二进制运算再转换回原来的进制来进行。

~0:生成一个全1的掩码。

7.逻辑运算

逻辑运算的计算方法:
全部非零参数都表明TRUE,0参数表明FALSE

逻辑运算的结果:
1-表明TRUE,或者,0-表明FALSE

逻辑运算和位运算的区别:

  • 只有当参数被限制为0或1时,逻辑运算才与按位运算有相同的行为。
  • 若是对第一个参数求值就能肯定表达式的结果,逻辑运算符就不会对后面的参数求值。

8.移位运算

通常而言,机器支持两种形式的右移:逻辑右移和算术右移。逻辑右移在左端补k个 0,算术右移是在左端补k个最高有效位的值。

C 语言标准并无明肯定义应该使用哪一种类型的右移。对于无符号数据(也就是以限定词 unsigned 声明的整型对象),右移必须是逻辑的。而对于有符号数据(默认的声明的整型对 象),算术的或者逻辑的右移均可以。

几乎全部的编译器 / 机器组合都对有符号数据使 用算术右移,且许多程序员也都假设机器会使用这种右移。

另外一方面,Java 对于如何进行右移有明确的定义。表达式 x>>k 会将 x 算术右移 k 个位置, 而 x>>>k 会对 x 作逻辑右移。

整数表示

1.整型数据类型
整型数据类型——表示有限范围的整数,每种类型都能用关键字来指定大小,还能够指定是非负数(unsigned)仍是负数(默认)。这些不一样大小的分配的字数会根据机器的字长和编译器有所不一样。

要用C99中的“long long”类型,编译是要用 gcc -std=c99

2.无符号数的编码
注意无符号数的二进制表示的一个重要性质:每一个介于0~2^w-1之间的整数都有惟一一个w为的值编码,函数为一个双射。

即0-(2^w)-1中的每个整数和长度为w的位向量是一一对应的。

3.补码编码(有符号数的编码)

关于补码:将字的最高有效位解释为负权。
有符号数的其余表示方法:
原码
反码

4.有符号数和无符号数的转换

强制类型转换

从位级角度考虑。

强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。即:这些位上的值不变,可是因为最高有效位的权重发生变化,从而致使结果发生改变。

5.c语言中的有符号数和无符号数及其转换

转换原则:底层的位保持不变。

6.扩展一个数字的位表示

扩展——从一个较小的数据类型转换为较大的数据类型,同时保持数值不变。

1).零扩展

将一个无符号数转换为一个更大的数据类型。只需在开头加上0便可。

2).符号扩展

将一个补码数字转换为一个更大的数据类型。最高有效位是什么,就添加什么。

7.截断数字

不用额外的位来扩展数值,而是减小表示一个数字的位数。而这么作可能会改变它的值,这也是溢出的一种形式。

将一个w位的数截断为k位数字时,就会丢弃高w-k位。

对于无符号数x来讲,截断它到k位的结果就至关于计算 xmod (2^k)

对于有符号数来讲,先按照无符号数截断,而后再转化为有符号数。

整数运算

1.无符号加法 本质上就是模运算,mod 2的w次幂。

考虑两个非负整数x和y,知足0≤x, y≤2w-1。每一个数都能表示为w位无符号数字。然而,若是计算它们的和,咱们就有一个可能的范围0≤x + y≤2w+1-2。表示这个和可能须要w + 1位。这种持续的“字长膨胀”意味着,要想完整地表示算术运算的结果,要对字长作限制。

算数运算溢出:一个算术运算溢出,是指完整的整数结果不能放到数据类型的总长限制中去。

2.补码加法

两个数的w位补码之和与无符号之和有彻底相同的位级表示。

溢出

补码加法的溢出状况比无符号运算更为复杂,分为正溢出、正常、负溢出。正溢出就是超过正数的最大范围,负溢出就是超过负数的最大范围。

但本质仍然是模运算,模掉w位的补码最高有效位的权重2的w次幂。

3.补码的非
(1)补码的非运算

4.无符号乘法
范围在0≤x, y≤ 2w-1内的整数x和y能够表示为w位的无符号数,可是它们的乘积x · y的取值范围为0到(2w-1)2 = 22w-2w+1+1之间。这可能须要2w位来表示。不过,C语言中的无符号乘法被定义为产生w位的值,就是2w位的整数乘积的低w位表示的值。能够看做等价于计算乘积模2w。

5.补码乘法
c语言中的有符号乘法是经过将2w位的乘积截断为w位的方式实现的。也就是说,须要mod 2的w次幂。
因此,对于无符号和补码乘法来讲,乘法运算的位级表示都是同样的。

6.乘以常数

在机器运算中,乘法老是很慢的,而加法和移位(左移)是相对较快的。因此在编译器中,会使用移位和加法运算组合的方式来代替乘以常数因子。这种方法对于无符号运算和补码运算都是适用的。

7.除以2的幂

机器运算中,除法比乘法更慢。当被除数为2的整数次幂时,经过右移来解决。右移时须要区分无符号数和补码。

须要注意:整数除法老是舍入到零

1).无符号数——逻辑右移

无符号数除以2的k次幂,就等同于对其逻辑右移k位。

2).补码——算术右移

补码进行算术左移时,须要考虑补码数的正负,由于整数除法老是舍入到零,无符号数中没有负数没必要担忧,但补码中有正有负,正数向下舍入到零,负数应该向上舍入到零。因此这里涉及到在移位前偏置。
也就是说:

x≥0时,除以2的k次幂等价于将x算术右移k位
x<0时,先将x加上(2^k)-1,再算术右移k位
与乘法不一样,这种右移方法不能推广到任意常数C。

八、整数运算的总结

计算机执行的“整数运算”其实是一种模运算。
不管运算数是以无符号形式仍是补码形式表示,都有彻底同样或者很是相似的位级行为。
谨慎使用unsigned数据类型,极可能会形成漏洞。

浮点数

浮点表示对形如V=x X (2^y)的有理数进行编码,对执行:
很是大的数字
很是接近于0的数字
做为实数运算的近似值
颇有用

一、二进制小数

小数的二进制表示法只能表示那些可以被写成x X (2^y)的数,其余的值只能近似的表示。

权重:
以小数点为界,
左边第i位,权重为2的i次幂
右边第i位,权重为2的-i次幂

二、IEEE浮点表示

IEEE浮点标准用V=(-1)^s ×M× 2^E 来表示一个数:
符号:s决定这个数是正仍是负。0的符号位特殊状况处理。
阶码:E对浮点数加权,权重是2的E次幂(可能为负数)
尾数:M是一个二进制小数,范围为1~2-ε或者0~1-ε(ε=1/2的n次幂)

编码规则:
单独符号位s编码符号s,占1位
k位的阶码字段exp编码阶码E
n位小数字段frac编码尾数M(同时须要依赖阶码字段的值是否为0)

两种精度:
单精度(float),k=8位,n=23位,一共32位;
双精度(double),k=11位,n=52位,一共64位。

三种被编码状况:(p70)
规格化的
非规格化的
特殊值

  • 规格化的值
    当exp的位模式既不全为0(数值0),也不全为1(单精度数值为255,双精度数值为2047)时,都属于这类状况。在这种状况中,阶码字段被解释为以偏置(biased)形式表示的有符号整数。也就是说,阶码的值是E = e-Bias,其中e是无符号数,其位表示为ek-1…e1e0,而Bias是一个等于2k-1-1(单精度是127,双精度是1023)的偏置值。由此产生指数的取值范围,对于单精度是-126~+127,而对于双精度是-1022~+1023。

  • 非规格化的值
    当阶码域为全0时,所表示的数就是非规格化形式。在这种状况下,阶码值是E = 1 - Bias,而尾数的值是M = f,也就是小数字段的值,不包含隐含的开头的1。非规格化值要这样设置偏置值的缘由是使阶码值为1-Bias而不是简单的-Bias彷佛是违反直觉的。咱们将很快看到,这种方式提供了一种从非规格化值平滑转换到规格化值的方法。

(1)阶码

阶码E = 1-Bias

(2)尾数

尾数M = f(小数字段的值,不包含隐含的1)

(3)非规格化的功能:

提供了一种表示数值0的方法
表示那些很是接近零的数。逐渐溢出。

  • 特殊值

特殊值是在阶码位全为1的时候出现的。当小数域全为0时,获得的值表示无穷,当s = 0 时是+∞,或者当 s = 1时是-∞。当咱们把两个很是大的数相乘,或者除以零时,无穷可以表示溢出的结果。

3.舍入

由于表示方法限制了浮点数的范围和精度,浮点运算只能近似地表示实数运算。所以,对于值x,咱们通常想用一种系统的方法,可以找到“最接近的”匹配值x',它能够用指望的浮点形式表示出来。

IEEE浮点格式定义了四种不一样的舍入方法:

  • 向偶舍入(默认方法)

即:将数字向上或向下舍入,是的结果的最低有效数字为偶数。

能用于二进制小数。

  • 向零舍入

即:把整数向下舍入,负数向上舍入。

  • 向下舍入

正数和负数都向下舍入。

  • 向上舍入

正数和负数都向上舍入。

默认的(即向偶舍入)方法能够获得最接近的匹配,其他三种可用于计算上界和下界。

四舍六入,五求偶。

4.浮点运算

IEEE标准指定了一个简单的规则,用来肯定诸如加法和乘法这样的算术运算的结果。把浮点值x和y当作实数,而某个运算⊙定义在实数上,计算将产生Round (x ⊙ y),这是对实际运算的精确结果进行舍入后的结果。当参数中有一个是特殊值(如-0、-∞或NaN)时,IEEE标准定义了一些使之更合理的规则。例如,定义1/-0将产生-∞,而定义1/+0会产生+∞。

浮点加法不具备结合性,这是缺乏的最重要的群属性。
浮点加法知足了单调性属性:若是a≥b,那么对于任何a、b以及x的值,除了NaN,都有x + a ≥ x + b。无符号或补码加法不具备这个实数(和整数)加法的属性。
对于任何a、b和c,而且a、b和c都不等于NaN,浮点乘法知足下列单调性:

五、c语言中的浮点数

全部的C语言版本提供了两种不一样的浮点数据类型:float和double。在支持IEEE浮点格式的机器上,这些数据类型就对应于单精度和双精度浮点。
较新版本的C语言,包括ISO C99,包含第三种浮点数据类型long double。对于许多机器和编译器来讲,这种数据类型等价于double数据类型。不过对于Intel兼容机来讲,GCC用80位“扩展精度”格式来实现这种数据类型,提供了比标准64位格式大得多的取值范围和精度。

int、float、double相互转换

int → float 不会溢出但有可能舍入
int/float → double 结果保留精确数值
double → float 可能溢出为±∞,因为精确度较小也有可能被舍入
float/double → int 向零舍入,可能溢出。

教材学习中的问题和解决过程

p48怎么样让负数等于正数?
由练习题2.21在负数x后加上U,可使其转换为(2^w+x)

课后做业中的问题和解决过程

(p35)2.13
问题:假设有两个函数bis和bic来实现位设置和位清除操做;只利用这两个函数实现按位 | 和^操做。

int bis(int x, int y);
int bis(int x, int y);

int bool_or(int x,int y)
{
    int result = bis(x,y);
    return result;
}
int bool_xor(int x,int y)
{
    int result = bis(bic(x,y),bic(y,x));
    return result;
}

解答: x^y = (x&~y) | (~x&y)知识点要掌握

问题:(p51)2.23

#include<stdio.h>
int fun1(unsigned word)
{
    return (int)((word<<24)>>24);
}
int fun2(unsigned word)
{
    return ((int)word<<24)>>24;
}

解决:
fun1()将word进行逻辑左移和右移后的结果转换为int型;
fun2()是将word先强制转换为int型,再进行的算数左移和右移。

w:0x87654321 fun1(w)=0x00000021,fun2(W)=0x00000021 (先进行左移即右侧六个十六进制位补f,以后右移的时候,由于最高有效位是0,因此前侧六个十六进制位补0)

(p52)2.25

解决:

以正常的浮点数数组输入,获得正常结果,可是输入0时有报错,如图:

解释:缘由应该在“i<=length-1”与以前声明的“unsigned length”的矛盾中。由于当输入的length是0时,length-1=0-1(无符号数运算),即模数加法,获得的是Umax。而任何数都是小于Umax的,因此比较式恒为真。则循环会访问数组a中的非法元素。简单的处理办法就是将length声明为int型

本周代码托管截图

代码连接

其余(感悟、思考等,可选)

此次以书上第二章内容为主,按照老师罗列的重点一一学习。关于这章的内容,不少知识都是看起来很熟悉,咱们都曾学习过或者接触过,重点仍是须要应用到实践中,都须要练习。这周主要看的是练习题,对于枯燥的文字知识,仍是题目解答能让咱们理解更深入,更明确。但在作题过程当中,公式也是很重要的,也须要翻回头重点看相关公式。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 100/100 2/2 25/25 安装了虚拟机并学习掌握核心的linux命令
第二周 100/200 1/3 30/55 虚拟机上的C语言编程
第三周 150/350 1/4 10/65 计算机中信息的表示和运算

参考资料

相关文章
相关标签/搜索