当前位置:
文档之家› 第三组程序及数据的机器级表示
第三组程序及数据的机器级表示
//代码段二 #include <stdio.h> int main() { double x=1.0, y=-1.0, z=0.0; printf ("Division by zero:%f%f\n", x/z, y/z); return 0; }
解释
从通用概念来说,除0本来就是不允许的, 即使允许,它的值也应该是无穷大。 int值采用的补码通用表示法,使得它 表示的整数范围有限,无法表示无穷 大这一概念; 而根据IEEE浮点表示法,有正无穷和 负无穷的表示,即指数全1和尾数全0, 所以可以不报错,而从得到的结果正 负无穷来指示结果出错。
舍入
现在来看一下本题中的数据: 1234567890=(01001001100101100000001011010010)2 = 1.001001100101100000001011010010 * 230
双精度浮点型浮点格式:
63 62 52 0
s
exp
frac
由 于 double 的 尾 数 位 有 52 位 , 因 此 double 类 型 可 以 精 确 表 示 1234567890,所以打印结果为1234567890.000000
简而言之,如果遇到 #INF / inf,就检查 是否发生了运算结果溢出除零。
Gdb调试 – 代码段一
不能执行return 0, 说明程序异常中断
重启动标志RF用来控制是否接受 调试故障。规定:RF=0时,表示 “接受”调试故障,否则拒绝之。 在成功执行完一条指令后,处理 机把RF置为0,当接受到一个非调 试故障时,处理机就把它置为1。
运行结果: -2147483648
运行结果: 程序结束
整数的除运算
这两个结果或许大家都感到很诧异,下面我们通 过汇编代码来研究到底发生了什么 Linux下两段代码运行情况: 代码一:
程序在汇编中解释为neg(取反) Tmin取反后还是其本身,不会 溢出
整数的除运算
neg:
NEG是汇编指令中的求补指令,NEG指令对操作数执 行求补运算:用零减去操作数按位取反后 加1。
10.010舍入后值为10.0
10.110舍入后值为11.0
舍入
现在来看一下本题中的数据: 1234567890=(01001001100101100000001011010010)2 = 1.001001100101100000001011010010 * 230
单精度浮点型浮点格式:
31 30 23 22 0
s
exp
frac
此时阶码E=30,在float表示范围之内,符号位为0。 由于float型尾数只有23位,而这里要表示的数尾数有30位,因 此需要舍入到二进制小数点右边23位,显然后7为1010010是大 于两个可能结果正中间的值,因此直接在小数点后第23位进一 位即可。 舍入后结果为1.00100110010110000000110 又1.00100110010110000000110 x 230=1234567936(即打印结果)
Gdb调试 – 代码段二
执行return 0,说明 程序没有异常中断
没有出现标志位RF。
03.浮点数舍入问题
例:将同一实数分别赋值给单精度和双精度类型变量, 然后打印输出。 #include <stdio.h> main(){ float a; double b; a = 123456.789e4; b = 123456.789e4; printf(“%f/n%f/n”,a,b);
格式:NEG OPR 执行的操作:(OPR)<-- —(OPR) 亦即把操作数按位求反后末位加1,因而执行的操作也可表示为: (OPR)<-- 0FFFFH — (OPR) + 1 NEG指令对标志的影响与用零作减法的SUB指令一样。
整数的除运算
这两个结果或许大家都感到很诧异,下面我们通 过汇编代码来研究到底发生了什么 Linux下两段代码运行情况: 代码二:
程序在汇编中解释为idivl(除法) Tmin/-1 = TMax+1,发生溢出, 程序中断。
整数的除运算
idivl:
idivl S R[%edx] = R[%edx]:R[%eax] % S; R[%eax] = R[%edx]:R[%eax] / S; 有符号除法,保存余数和商
divl:
divl S R[%edx] = R[%edx]:R[%eax] % S; R[%eax] = R[%edx]:R[%eax] / S; 无符号除法,保存余数和商
}
运行结果如下: 1234567936.000000 1234567890.000000 问题:为什么同一个实数赋值给float型变量和double型变 量,输出结果会有所不同呢?
舍入
由于表示方法限制了浮点数的范围和精度,浮点运算只能近似地 表示实数运算。因此对于某一值x,我们想要用一种系统的方法,用浮点形 式表示最接近的值,这就是舍入。 向偶数舍入是默认的方式,也被称为最接近的值的舍入。其采取 的方法是对于两个可能结果正中间的值,将数字向上或者向下舍入,使得 结果的最低有效数字是偶数,在二进制表示中最低有效位的值0认为是偶 数,1认为是奇数。 例如舍入到二进制小数点右边1位。
程序及数据的机器级表示
第三组 樊朝辉 孙懿 黄杰 任成琨 黄章冠 潘鑫 王嘉琦 杨玉茹
目录
CONTENTS
1 2 3
整数的除运算
整数除0和浮点数除0的问题
浮点数舍入问题
01.整数的除运算
针对下列两个小程序,给出运行结果,并解释为什么? 利用你所掌握的反汇编调试工具,佐证你的观点。
代码段一: int a = 0x80000000; int b = a / -1; printf("%d\n", b); 代码段二: int a = 0x80000000; int b = -1; int c = a / b; printf("%d\n", c);
整数的除运算
这两个结果或许大家都感到很诧异,下面我们通 过汇编代码来研究到底发生了什么 Linux下两段代码运行情况: 代码二:
将断点设置在除法进行的地方, 调试如图所示,抛出异常,程 序终止
02.整数除0和浮点数除
0的问题
代码示例
运行结果
运行结果
//代码段一 #include <stdio.h> int main() { int a=1, b=0; printf ("Division by zero:%d\n", a/b); return 0; }
浮点数中的INF
#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以 表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。
例如,当用 0 除一个整数时便会得到一个 #INF / inf值;相应的,如果用 0 除一个 负整数也会得到 -#INF / -inf 值。