datalab
本文最后更新于:2023年3月24日 晚上
计算机系统实验二 Datalab 实验报告
1.实验目的:
- 补充完整 bits.c 文件内容,完成实验;
- 了解机器中对整型、浮点数的存储方式;
- 熟悉位操作,完成一系列指令。
2.实验准备
- 学习 CSAPP 书上的相关信息表示部分;
- 配置好虚拟机环境。
3.实验任务
- 补充完整 bits.c 文件内容,并利用 btest 程序进行测试。
1.bitAnd
要求: 输出两个数按位与操作后的值。
实现:参数 x,y 分别按位取反后,进行或操作,最后再将结果取反即可(数学推导而成)
代码截图:
2.getByte
要求:将整型数据 x 的第 n 个字节取出。
实现:直接将 x 右移 n*8 个位后,与 0xFF 进行与操作,取出最后一个字节即可。
代码截图:
3.logicalShift
要求:实现逻辑右移,由于 >> 为算术右移,需要实现负数的逻辑右移。
实现:将 x 算术右移 n 位后,与 ~(1 << 31) >> n) << 1)
进行与操作,这样可以使负数算术右移后,前面的一串 1 改为 0 ,达到逻辑右移的目的。
代码截图:
4.bitCount
要求:计算出x中有多少个1。
实现:计算出每两位中1的个数,用对应的两位进行存储,随后计算每四位中,再计算每8位,最后可得到结果。
代码截图:
5.bang
要求:不使用逻辑取反的情况下实现逻辑取反。
实现:用x或其负数,再右移31位取符号位+1即可。利用了x取反后,符号位均为1,除x == 0外的特性。
代码截图:
6.tmin
要求:输出最小的二进制补码。
实现:最小的二进制补码是0x80000000。
代码截图:
7.fitsBits
要求:给出一个数,判断x 是否能最少被 n 位表示。
实现:对于正数,若 x 右移 n -1 位(这一个是符号位,不可缺少),剩余的都是0,即可,对于负数,剩余的应该都是1。
代码截图:
8.divpwr2
要求:输出x除以2的n次幂后,向0取整的结果。
实现:正数直接右移n位即可,负数需进行调整。
代码截图:
9.negate
要求:实现取反。
实现:直接按位取反+1(取补码)即可。
代码截图:
10.isPositive
要求:判断 x 是否大于0;
实现:对 x == 0 单独讨论即可
代码截图:
11.isLessOrEqual
要求:判断x是否小于等于y
实现:用y-x,判断符号位即可。
代码截图:
12.ilog2
要求:求xlog2的值
实现:在这个实现中,我们首先将结果初始化为0。然后,我们使用位运算符逐步将结果设置为x的二进制表示中最高位1的位置。具体来说,我们首先检查x的高16位是否有1,如果有,则将结果的高4位设置为4。然后,我们将x右移结果的值,以便在下一步中检查剩余的位。我们重复这个过程,直到我们检查了x的所有位。最后,我们返回结果。
代码截图:
13.float_neg
要求:浮点数取反
实现:先将NaN直接返回无需操作,其余数据修改符号位即可。
代码截图:
14.float_i2f
要求:将int转换为float
实现:首先使用0x80000000获取x的符号位,如果x的符号位上是1,则求其补码。这一过程通过if判断实现。之后,通过while循环寻找除符号位外最高位1的位置,由于0x0和0x80000000去除符号位后对循环跳出条件有影响(会陷入死循环),故作为特殊边界值取出,单独做返回值。找到最高位1的位置后加上偏置量即可得到阶码的数值,再通过移位操作即可转移到指定的地方。对x进行左移操作,使32位中仅保留尾数相关的信息。取前23位作为尾数基础部分,后9位作为判断舍入的依据。若后9位不处于中间值则按照“大于进位,小于保留原状态”的方式处理。若处于中间值,则看23位的最后一位,如果它是1则选择“进位+1”,如果它是0则选择“保持原状态”。最后,整合各部分结果即可得到题目要求的结果。
代码截图:
15.float_twice
要求:浮点数乘二
实现:对于非规格化值,需要将尾数左移一位,若进位,阶码需+1。对于规格化值,阶码+1。特殊值直接返回本身就行。
代码截图:
检查是否违规:
dlc检查:
btest检查:
关于btest有一个项目没过关:是环境问题,0肯定可以用32位表示的。
4.实验总结:
实验中出现的问题:
- 环境的差异性,导致有一个样例未能通过,但代码是没问题的。
- 虚拟机的不稳定性,虚拟机总是死机。
实验心得
- 操作位是一个十分有意思的事情,利用有限的操作达成一个目的。
- 体会到更底层方面,仅用加法、位移这类操作实现计算机的艰难与智慧。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!