HNU-计算机系统-实验二

本文是一份关于计算机系统实验的报告,详细描述了如何通过修改bits.c文件实现一系列位运算和浮点数处理任务,包括按位与、字节提取、逻辑移位、1的个数计数等,并面临了编译器兼容性和难度较大的实验挑战。
摘要由CSDN通过智能技术生成

《计算机系统》

第二次实验报告

班级:

学号:

姓名:

目录

1 实验项目一

1.1 项目名称

1.2 实验目的

1.3 实验资源

2 实验任务

2.1 实验任务A

2.2 实验任务B

2.3 实验任务C

3 总结

3.1 实验中出现的问题

3.2 心得体会

  1. 实验项目一
    1. 项目名称

CS:APP Data Lab

    1. 实验目的

1)该实验室旨在帮助学生通过修改 bits.c 文件,使其能够通过 btest 测试,并且不违反任何编码准则。

    1. 实验资源

文件:

Makefile:用于编译 btest、fshow 和 ishow 等程序。

README:本文件。

bits.c:需要修改的文件,其中包含了您需要完成的任务。

bits.h:头文件。

btest.c:主要的 btest 程序。

dlc:用于检查代码是否符合编码准则的编译器二进制文件。

driver.pl:用于自动评分的驱动程序。

fshow.c:用于检查浮点数表示的实用程序。

ishow.c:用于检查整数表示的实用程序。

修改 bits.c 并使用 dlc 进行检查:

通过阅读 bits.c 文件中的说明,了解您需要遵循的编码规则。

使用 dlc 编译器(./dlc bits.c)自动检查您的 bits.c 是否符合编码准则。如果没有问题,dlc 将会静默返回;否则,它会输出问题信息。

使用 btest 进行测试:

使用 Makefile 中的命令编译并运行 btest 程序(make btest 和 ./btest [optional cmd line args])。

每次更改 bits.c 后,都需要重新编译 btest 程序。

btest 将通过运行数百万个测试用例来测试您的代码,测试范围涵盖了各种情况,如 Tmin、零等。如果检测到错误,btest 将打印出失败的测试用例,错误的结果和预期结果。

辅助程序:

该实验室提供了 ishow 和 fshow 程序,用于帮助您解析整数和浮点数表示。这两个程序接受一个十进制或十六进制数字作为参数。

  1. 实验任务
    1. 实验任务A

任务名称:补全bits.c里的函数,依据条件限制并实现各个函数的功能,接着使用dlc编译器检查bits.c文件并使用make clean与make btest使用 Makefile 中的命令编译并运行 btest 程序,最后使用./btest查看自己写的函数能否通过全部测试样例。

1.按位与

这段代码实现了使用 ~ 和 | 运算符计算 x 和 y 的按位与(&)操作。

运用德摩根定律公式得到,~(~x | ~y)= x & y。

2.提取字节

这段代码实现了从一个 32 位整数 x 中提取指定字节的功能。

首先,一个字节含8位,32位可以分成4个字节。输入的n代表第几个字节,我们转成n*8位,接着将x右移n*8位,把要提取的字节存入第八位,最后与0xFF得到要提取的字节。

3.逻辑移位

这段代码实现了对一个 32 位整数 x 进行逻辑右移 n 位的操作。

由于直接对x右移的结果是算术右移,即会将可能的符号位向右补齐。所以我们要构造一个左边n位都是0的数与我们的结果相与,就可以消掉这个影响。

首先,我们需要一个mask掩码,用于屏蔽掉在逻辑右移操作中产生的符号位扩展。构造0x80000000,接着右移n位左移1位并取反,使左边n位为0,右边全为1。

4.1的个数

这段代码实现了对一个 32 位整数 x 进行寻找有几位是1的操作。

用到了分治法的思想,第一次两位两位的看,用每两位记录多少个1,如果是11,那么结果记录10,10或01记录01,00记录00.接着分别用四位,八位,16位,32位记录多少个1,最后得到的x的值就是32位有多少个1。

5. 逻辑非

这个函数计算逻辑非(!)操作

如果x为0,那么(x | (~x + 0x1)) >> 31的结果一定为0,结果为1;如果x非0,那么(x | (~x + 0x1)) >> 31的结果一定为-1,结果就是0。

6.最小的二进制补码整数

这个函数返回最小的二进制补码整数。

最小的就是0,0的二进制补码表示就是0x80000000。

7.合适的位数

这个函数检查整数 x 是否能够用 n 位的二进制补码表示。

若x可以被n位补码表示,首先符号位占一位,则x的第n位到第31位应该都是无效位,则将x先左移(32-n)位再右移(32-n)位,若与原来的x相同(使用异或来判断),则它的确可以被表示。

8.除以 2 的 n 次方

这个函数用于计算 x 除以 2 的 n 次方,其中 n 在 0 到 30 之间,向零取整。

如果是正数,那么不需要设置偏移量,x会自动向下取整即向零取整,所以bias为0;如果是负数,x会自动向下取整,那就不是向0取整了,所以我们需要设置一个偏移量,加上偏移量结果就会向0舍入。

9.取反

这个函数用于返回整数 x 的相反数。

对于补码来说,x的相反数等于x取反再加1。

10.是否为正

这个函数用于检查整数 x 是否为正数。

如果x为正数,那么符号位为0且!x为0,那么结果为1;如果x为0,那么符号位为0,但是!x为1,所以结果为1;如果x为负数,那么符号位为1,结果是0。

11.是否小于

这个函数判断 x 是否小于等于 y,如果是则返回 1,否则返回 0。

先设置一个标志位sign用于判断x和y是同号还是异号,接着分情况讨论。

当同号时,如果x<y,那么x-y的为负符号位为1;当x=y时,x-y为0;当异号时,x的符号位为0。这三种情况返回1,其他返回0。

12.以 2 为底的对数

这个函数的目标是计算正整数 x 的以 2 为底的对数。采用二分法来逼近结果并得到答案。

y 就是二分法的指针,用于记录当前逼近的位数。第一步检查 x 的高 16 位是否有非零位,如果有,则 y 加上 16;第二步继续检查 x 的高 8 位是否有非零位,如果有,则 y 加上 8;第三步继续检查 x 的高 4 位是否有非零位,如果有,则 y 加上 4;第四步继续检查 x 的高 2 位是否有非零位,如果有,则 y 加上 2;第五步继续检查 x 的高 1 位是否有非零位,如果有,则 y 加上 1。

最后得到的y就是y指针指向的数。

13.单精度浮点数的负值

这个函数的目标是返回单精度浮点数的负值。

这个函数首先使用位掩码提取了浮点数的阶码和尾数部分,并检查了是否为 NaN(阶码全1且尾数非零)。如果是 NaN,则直接返回原值;如果不是 NaN,则将最高位(符号位)取反,即得到了负值的表示。

14.单精度浮点数

这个函数的目标是将整数 x 转换为单精度浮点数的表示形式。

它需要处理符号位、阶码和尾数,并且可能需要对尾数进行舍入。

如果x是0,直接返回0;否则首先提取了 x 的符号位,并将 x 变为非负数abs_x和mask。然后通过对mask移位操作并和0x80000000比较找到了 x 的最左边的非零位,记录num以计算阶码。接着计算了尾数部分,并判断尾数部分是否需要舍入,如果需要就按照4舍6入5向偶舍入的规律对frac和exp操作,最后消除frac进位超限的问题。最后将符号位、阶码和尾数组合成了结果。

15.浮点数 f 的两倍

这个函数的目标是计算浮点数 f 的两倍,即返回 2*f。

这个函数首先处理了特殊情况:如果输入是正0、负0、无穷大或NaN,则直接返回原值。然后提取了符号位和阶码,以及尾数。根据阶码的值,对尾数进行了相应的处理:如果阶码为0,则将尾数左移1位,并根据尾数最高位是否为1来决定是否对阶码加1。最后将符号、阶码和尾数组合成了结果。

  1. 总结
    1. 实验中出现的问题

1.实验二的引导部分做的实在不好,一开始花了很久才看懂要做什么,并且函数的要求也挺有难度,第一次做可能需要很久的时间。

2.实验二的编译器不是很好,有些函数在dev-c++上运行结果正确,在btest里运行就错了,并且fitbits函数在32位的ubuntu过了,在64位ubuntu运行一直过不了,直到改了makefile里的设置才输出。

3.最后几个浮点数和二分法分治法的函数难度很大,我自己写了很久,又找同学和GPT改进才完成

    1. 心得体会

虽然过程艰难,但是做完实验还是觉得自己对位运算和浮点数有了更深的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值