信息安全系统设计基础第三周学习总结

第二章  信息的表示和处理

一、前言

1、二进制数字称为位(bit)

2、三种重要的数字表示:无符号编码、补码(有符号)、浮点数(科学计数法)

3、浮点运算虽然溢出会产生特殊的值 + ∞,但是一组正数的乘积总是正的。由于表示的精度有限,浮点运算是不可结合的。 整数运算和浮点数运算会有不同的数学属性是因为它们处理数字表示有限性的方式不同—整数的表 示虽然只能编码一个相对较小的数值范围,但是这种表示是精确的 ;而浮点数虽然可以编码一个较大的数值范围,但是这种表示只是近似的。 

二、信息存储

1、大多数计算机使用 8 位的块,或者字节(byte),作为 最小的可寻址的存储器单位。机器级程序将存储器视为一个非常大的字节数组,称为虚拟存储器(virtual memory)。存储器的每个字节都由 一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合称为虚拟地址空间(virtual address space)。

2、编译器和运行时系统是如何将存储器空间划分为更可管理的单 元,以存放不同的程序对象(program object),即程序数据、指令和控制信息。 C 语言中 一个指针的值(无论它是指向一个整数、一个结构或是某个其他程序对象)都是某个存储块的第 一个字节的虚拟地址。 

3、十六进制表示法

一个字节由 8 位组成。在二进制表示法中,它的值域是 000000002 ~ 111111112 ;如果用十进制整数表示,它的值域就是 0 ~ 255。以 16 为基 数,或者叫十六进制(hexadecimal)数,来表示位模式。十六进制(简写为“hex”)使用数字‘0’~‘9’,以及字符‘A’~‘F’来表示 16 个可能的值。用十六进制书写,一个字节的值域为 0016 ~ FF16。 

以 0x 或 0X 开头的数字常量被认为是十六进制的值。字符‘A’~‘F’既可以 是大写,也可以是小写,甚至是大小写混合。 

编写机器级程序的一个常见任务就是在位模式的十进制、二进制和十六进制表示之间人工进 行转换。 

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

4、每台计算机都有一个字长(word size),指明整数和指针数据的标称大小(nominal size)。因 为虚拟地址是以这样的一个字来编码的,所以字长决定的最重要的系统参数就是虚拟地址空间的 最大大小。对于一个字长为 w 位的机器而言,虚拟地址的范围为 0 ~ 2w-1,程序最多 访问 2w 个字节。 

5、数据大小

C 的数据类型 char 表示一个单独的字节。尽管 “char”是由于它被用来存储文本串中的单个字符这一事实而得名,但它也能用来存储整数值。

C 的数据类型 int 之前还能加上限定词 short、long,以及最近的 long long,以提供各种 大小的整数表示。 

准确的字节数依赖于机 器和编译器。“短”整数分配有 2 个字 节,而不加限定的 int 为 4 个字节。“长”整数使用机器的全字长。ISO C99 引入的“长长”整 数数据类型允许 64 位整数。

单精度(在 C 中声明为 float)和双精度(在 C 中声明为 double)。格式分别使用 4 字节和 8 字节。 

6、寻址和字节顺序

这个对象的地址是什么,以及在存 储器中如何排列这些字节。

某些机器选择在存储器中按照从最低有效字节到最高 有效字节的顺序存储对象,而另一些机器则按照从最高有效字节到最低有效字节的顺序存储。前 一种规则— 最低有效字节在最前面的方式,称为小端法(little endian)。大多数 Intel 兼容机都 采用这种规则。后一种规则— 最高有效字节在最前面的方式,称为大端法(big endian)。大多 数 IBM 和 Sun Microsystems 的机器都采用这种规则。 

网络应用程序 的代码编写必须遵守已建立的关于字节顺序的规则,以确保发送方机器将它的内部表示转换成网络 标准,而接收方机器则将网络标准转换为它的内部表示。 

反汇编器是一种确定可执行程序文件所表示的指 令序列的工具。 

当阅读此类小端法机器生成的机器级程序表示时,经 常会将字节按照相反的顺序显示。书写字节序列的自然方式是最低位字节在左边,而最高位字节 在右边,这正好和通常书写数字时最高有效位在左边,最低有效位在右边的方式相反。

字节顺序变得可见的第三种情况是当编写规避正常的类型系统的程序时。在 C 语言中,可 以使用强制类型转换(cast)来允许以一种数据类型引用一个对象,而这种数据类型与创建这个 对象时定义的数据类型不同。 

Linux 32、Windows 和 Linux 64 上这说明它们是小端法机器 ;而Sun 是大端法机器。 

多字节对象都被存储为连续的字节序列,对 象的地址为所使用字节中最小的地址。 

Linux 32、Windows 和 Sun 的机器使用 4 字节地址,而 Linux 64 使用 8 字节地址。 

十进制数字 x 的 ASCII 码正好是 0x3x,而终止字节的十六进制表示为 0x00。在使用 ASCII 码作为字符码的 任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因而,文本数据比二进制数据 具有更强的平台独立性。 

Java 编程语言使用 Unicode 来表示字符串。对于 C 语言也有支持 Unicode 的程序库。 

7、布尔代数

二进制值是计算机编码、存储和操作信息的核心 。

最简单的布尔代数是在二元集合 {0,1} 基础上的定义。 

创立信息理论领域的 Claude Shannon(1916 — 2001)首先建立了布尔代数和数字逻辑之间的联系。

布尔运算扩展到位向量的运算,位向量就是有固定长度为 w、由 0 和 1组成的串。位向量的运算可以定义成参数的每个对应元素之间的运算。 

位向量一个很有用的应用就是表示有限集合。

 

 布尔运算 | 和 & 分别对应于集合的并和交,而 ~ 对应于于集合的补。 

这个掩码表示的就是设置为有效信号的集合。 

8、C语言中的位级运算

确定一个位级表达式的结果最好的方法,就是将十六进制的参数扩展成二进制表示并执行二进制运算,然后再转换回十六进制。

位级运算的一个常见用法就是实现掩码计算,这里掩码是一个位模式,表示从一个字中选出的位的集合。

掩码 0xFF(最低的 8 位为 1)表示一个字的低位字节 。

9、C语言中的逻辑运算

10、C语言中的移位运算

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

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

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

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

三、整数表示

1、整型数据类型

C语言支持多种整形数据类型——表示有限范围的整数。

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

2、无符号数的编码  p39-44

假设一个整数数据类型有w位。我们可以将位向量写成x→,表示整个向量,或者写成[xw-1 ,xw-2,…,x0],表示向量中的每一位。把x→看做一个二进制表示的数,就获得了x→的无符号表示。

无符号二进制有一个很重要的属性,就是每个介于0~2^w-1之间的整数都有唯一一个w为的值编码,函数为一个双射。

3、有符号数和无符号数的转换  p44-47

C语言允许在各种不同的数字数据类型之间做强制类型转换。将负数转换成无符号数可能会得到0。如果转换的无符号数太大以至于超出了补码能够表示的范围,可能会得到TMax。

C语言允许有符号数与无符号数之间的转换,转换的原则是底层的位表示保持不变

4、C语言中的有符号数和无符号数  p47-49

5、扩展一个数字的位表示

将一个无符号数转换为一个更大的数据类型,只需在表示的开头添加0,即0扩展;将一个补码数字转换为一个更大的数据类型可以执行符号扩展,规则是表示中添加最高有效位的值的副本。

6、截断数字  p51

将一个w位的数假设我们不用额外的位来扩展一个数值,而是减少表示一个数字的位数。x=[xw-1 ,xw-2,…,x0]截断为一个k位的数字时,会丢弃高w-k位,得到一个位向量[xk-1 ,xk-2,…,x0],截断一个数字可能会改变他的值——溢出的一种形式。

注意:有符号数到无符号数的隐式强制类型转换导致了某些非直观的行为。而这些非直观的特性经常导致程序错误,并且这种包含隐式强制类型转换细微差别的错误很难被发现。因为这种强制类型转换是在代码中没有明确指示的情况下发生的,程序员经常忽视了它的影响。

7、补码编码

最常见的有符号数的计算机表示方式就是补码形式。在这个定义中,将字的最高有效位解释为负权。

所能表示的数值范围[-2^(w-1)~2^(w-1)-1],在可表示的范围内每个数字 都有一个唯一的w位的补码编码,函数为一个双射。

注意

  • 补码的利用寄存器的长度是固定的特性简化数学运算。想想钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。

  • 补码的范围是不对称的:|TMin| = |TMax| + 1,也就是说,TMin没有与之对应的正数。这导致补码运算的某些特殊的属性,并且容易造成程序中细微的错误。之所以会有这样的不对称性,是因为一半的位模式(符号位设置为1的数)表示负数,而一半的数(符号位设置为0的数)表示非负数。因为0是非负数,也就意味着能表示的正数比负数少一个。

  • 最大的无符号数值刚好比补码的最大值的两倍大一点:UMaxw = 2 TMaxw + 1。补码表示中所有表示负数的位模式在无符号表示中都变成了正数。

    • 反码:除了最高有效位的权是-(2w-1-1)而不是-2w-1,它和补码是一样的

    • 原码:最高有效位是符号位用来确定剩下的位应该取负权还是正权。

8、符号数的其他表示方法

  • 反码:除了最高有效位的权是-(2w-1-1)而不是-2w-1,它和补码是一样的

  • 原码:最高有效位是符号位用来确定剩下的位应该取负权还是正权。

四、整数运算

1、无符号加法

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

无符号运算可以被视为一种模运算形式。无符号加法等价于计算和模上2w。可以通过简单的丢弃x + y的w + 1位表示的最高位,来计算这个数值。

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

2、补码加法

3、补码的非

范围在-2w-1≤x < 2w-1中的每个数字x都有+wt下的加法逆元。定义对于范围-2w-1 ≤ x < 2w-1内的x,补码的非运算-wt如下:

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。

因此,w位无符号乘法运算* wu的结果为:

5、补码乘法

C语言中的有符号乘法是通过将2w位的乘积截断为w位的方式实现的。

6、乘以常数

编译器使用了一项重要的优化,试着用移位和加法运算的组合来代替乘以常数因子的乘法。将整数拆成2的幂相加,再利用移位进行计算(左移),最后将结果相加。 同理,对于非负数来说,算术右移k位与除以2^k是一样的。

我们可以在移位之前“偏置”(biasing)这个值,通过这种方法修正这种不合适的舍入。这种技术利用的属性是:对于整数x和任意y > 0的y,有 「x/y例如,当x = -30且y = 4,我们有x + y - 1 = -27,而 「-30/4我们有x + y - 1 = -29,而 「-32/4这里0 ≤ r < y,得到(x + y - 1)/y = k + ( r + y - 1) / y,因此时,后面一项等于0,而当r > 0时,等于1。也就是说,通过给x增加一个偏量y - 1,然后再将除法向下舍入,当y整除x时,我们得到k,否则,就得到k + 1。因此,对于x < 0,如果在右移之前,先将x加上2k-1,那么我们就会得到正确舍入的结果了。

四、浮点数

浮点表示对形如V = x×2y的有理数进行编码。它对执行涉及非常大的数字(|V |>

0)、非常接近于0(|V |<<1)的数字,以及更普遍地作为实数运算的近似值的计算,是很有用的。

1、二进制小数

2、IEEE浮点表示

IEEE浮点标准用V = (-1)^s × M × 2^E的形式来表示一个数:

  • 符号:s决定这个数是负数(s=1)还是正数(s=0),而对于数值0的符号位解释作为特殊情况处理。
  • 尾数:M是一个二进制小数,它的范围是1~2-ε,或者是0~1-ε。
  • 阶码:E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。

将浮点数的位表示划分为三个字段,分别对这些值进行编码:

  • 一个单独的符号位s直接编码符号s。
  • k位的阶码字段exp = ek-1…e1e0编码阶码E。
  • n位小数字段frac = fn-1…f1 f0编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。

给定了位表示,根据exp的值,被编码的值可以分为以下三种情况:

  • 情况1:规格化的值

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

  • 情况2:非规格化的值

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

非规格化数有两个用途:

首先,它们提供了一种表示数值0的方法,因为使用规格化数,我们必须总是使M≥1,因此我们就不能表示0。

另外一个功能是表示那些非常接近于0.0的数。它们提供了一种属性,称为逐渐溢出,其中,可能的数值分布均匀地接近于0.0。

  • 情况3:特殊值

当指阶码全为1的时候出现的。当小数域全为0时,得到的值表示无穷,当s = 0 时是+∞,或者当 s = 1时是-∞。当我们把两个非常大的数相乘,或者除以零时,无穷能够表示溢出的结果。

3、舍入

**舍入:**因为表示方法限制了浮点数的范围和精度,浮点运算只能近似地表示实数运算。因此,对于值x,我们一般想用一种系统的方法,能够找到“最接近的”匹配值x',它可以用期望的浮点形式表示出来。

**在两个可能值的中间确定舍入方向:**一种可选择的方法是维持实际数字的下界和上界。例如,我们可以确定可表示的值x-和x+,使得x的值位于它们之间:x- ≤ x≤ x+。

IEEE浮点格式定义了四种不同的舍入方式。

  • 默认的方法是找到最接近的匹配,而其他三种可用于计算上界和下界。
  • 其他三种方式产生实际值的确界。这些方法在一些数字应用中是很有用的。向零舍入方式把正数向下舍入,把负数向上舍入,得到值x^,使得| x ^|≤| x |。向下舍入方式把正数和负数都向下舍入,得到值x-,使得x-≤x。向上舍入方式把正数和负数都向上舍入,得到值x+,满足x≤x+。

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,浮点乘法满足下列单调性:

5、C语言的浮点数

所有的C语言版本提供了两种不同的浮点数据类型:float和double。在支持IEEE浮点格式的机器上,这些数据类型就对应于单精度和双精度浮点。

较新版本的C语言,包括ISO C99,包含第三种浮点数据类型long double。对于许多机器和编译器来说,这种数据类型等价于double数据类型。不过对于Intel兼容机来说,GCC用80位“扩展精度”格式来实现这种数据类型,提供了比标准64位格式大得多的取值范围和精度。

 

============遇到的问题==================

对于公式的理解还是不太够,虽然老师说公式可以不看,但是不看公式的话后面会有很大一部分内容无法理解,练习做起来也麻烦。所以我花了很多时间在公式上,但是到头来收益还不如以前上的汇编、计算机导论对数制的理解简单。代码也有很多需要构造的部分。如果没有答案,我觉得可能就不知道怎么写了。

posted @ 2015-10-03 14:14  20135313吴子怡  阅读(396)  评论(1编辑  收藏  举报