实验原理与内容
本实验每位学生拿到一个datalab-handout.tar文件。学生可以通过U盘、网盘、虚拟机共享文件等方式将其导入到Unbuntu实验环境中,选择合适位置存放。然后在Ubuntu环境下解压。解压后,根据文件中的叙述和要求更改bits.c文件。本次实验的主要操作方式为:使用C语言的位操作符实现题目要求。
需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。
1.位操作
表1列出了bits.c中一组操作和测试位组的函数。其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。
也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。
表1 位操作题目列表
本题分数 | 函数名 | 功能 | 约束条件 | 最多操作符数 |
1 | isZero | 判断变量x是否为0。如果为0,则返回1;否则,返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 2 |
1 | specialBits | 构建0xffca3fff,并返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 3 |
1 | upperBits | 根据输入的变量n,构建一个高n位为1其他位为0的数,并返回该值。 注:0<= n <=32 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 10 |
1 | bitMatch | 构建一个比特序列(int型),构成规则如下:如果x和y在某一个bit位置的值相同,则此序列的相应位置为1,否则该位置值为0。 | 仅可以使用以下操作符: ~ & | 14 |
1 | bitOr | 计算按比特或(x | y),并将计算结果返回。 | 仅可以使用以下操作符: ~ & | 8 |
4 | logicalNeg | 使用位操作符实现逻辑非(!x)操作,并将取逻辑非之后的结果返回。 | 仅可以使用以下操作符: ~ & ^ | + << >> | 12 |
4 | bitParity | 如果x中包含奇数个0,则返回1;否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 20 |
2 | byteSwap | 将x的第n字节和第m字节交换, 0 <= n <= 3, 0 <= m <= 3, 然后将交换后的值返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 25 |
2 | getByte | 提取x的第n个字节。0 <= n <= 3 (0代表最最低为字节,3代表最高位字节),并将其返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 6 |
2 | oddBits | 返回一个32bit数,这数的所有第奇数个bit位置的值为1。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 8 |
3 | replaceByte | 将x的第n个字节用 c 进行替换, 0 <= n <= 3, 0 <= c <= 255 并将替换后的结果返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 10 |
3 | rotateLeft | 将x向左循环移位n个bit。循环移位是指左边移除去的比特自动填充到右边空出的位置上。 0 <= n <= 31,并将循环移位后的值返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 25 |
2.补码运算
表2列出了bits.c中一组使用整数的补码表示的函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。
表2 补码运算题目列表
本题分数 | 函数名 | 功能 | 约束条件 | 最多操作符数 |
2 | negate | 将输入参数x的值取相反数,返回-x。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 5 |
4 | absVal | 计算变量x的绝对值,并将其绝对值返回。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 10 |
3 | isGreater | 如果x > y,则返回1,否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 24 |
2 | isNegative | 如果x < 0,返回1;否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 6 |
4 | isPower2 | 如果x是2的整数次幂,则返回1;否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 20 |
3 | addOK | 如果x+y没有溢出,则返回1;否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 20 |
3 | subtractionOK | 如果x-y没有溢出,则返回1;否则返回0。 | 仅可以使用以下操作符: ! ~ & ^ | + << >> | 20 |
3.浮点数操作
表3列出了bits.c中一组浮点数二进制表示的操作函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。注意输入参数和返回结果均为unsigned int类型,但应作为单精度浮点数解释其32 bit二进制表示对应的值。
表3 浮点数操作题目列表
本题分数 | 函数名 | 功能 | 约束条件 | 最多操作符数 |
2 | floatAbsVal | 通过bit级操作返回一个float型浮点数的绝对值。如果输入参数为NaN,则直接返回输入参数的原值。 | 可以使用任何的操作符,包括||和&&。也可以使用if,while。 | 10 |
2 | floatIsEqual | 判断两个浮点数是否相等,如果相等则返回1,否则返回0。 如果输入参数中含有NaN,则返回0。 注:+0和-0被当作相等的情况对待。 | 可以使用任何的操作符,包括||和&&。也可以使用if,while。 | 25 |
实验过程与结果(可贴图)
安装gcc和ubuntu
isZero函数
isZero函数可能会接受一个数字作为输入,然后返回一个布尔值,该布尔值表示该数字是否为零。如果是零,函数返回True;如果不是零,函数返回False。
Negate函数
这个函数将接受一个数值作为输入,并返回其相反数。如果输入是正数1,则返回-1;如果输入是负数-1,则返回1;如果输入是零0,则返回0。
specialBits函数
这个函数目前学的还不是很懂,去一个地址再返回一个新的地址。
upperBits函数
这个函数检查函数为零的位,不为零跳到下一位,直到所有位为非零为止。
bitMatch函数
这个函数会返回一个x与y相等的位,用&操作符能恰好解决。
bitOr函数
这个函数会返回一个x与y相或的数,先对两个数进行取反,用&操作符最后用~操作符能恰好解决。
AbsVal函数
absval 函数用于计算一个数的绝对值。它接受一个数值作为输入,并返回该数值的绝对值。
我们可以先对数值进行左移再取反,最后结合异或操作符,能使函数达到这个功能。
logicalNeg函数
这个函数实现了如果x为0,则结果为0;如果x不为0,则结果为-1的补码表示。
将上一步的结果+1,得到0或1,就可以实现逻辑非操作。
bitParity函数
这个函数巧妙运用左移和右移操作符。
Byteswap函数
这个函数可以实现字节转换,我们可以巧妙运用左移和右移操作符,从而实现这个功能。
Getbyte函数
这个函数主要是要知道有效字节的位置,我们用右移操作符和左移操作符寻到最低位置,在用&0xff找到有效位的8位,就是要找的字节。
Isgreater函数
这个函数可以使得返回一个较大的值,类似max。
Isnegative函数
这个函数可以实现判断输入整数是否为负数的的操作,负数返回1,其它返回0。
巧妙运用右移操作符和取反,可以达到此效果。
Ispower2函数
这个函数实现判断x是不是为2的幂的操作。
Addok函数
这个函数可以实现两个数相加的值,判断这个值是不是溢出的操作,巧妙运用非操作符可以实现此功能。
Subtractionok函数
这个函数可以发现两个数的差,有没有造成溢出的操作,巧妙运用非操作符可以实现此功能。
Oddbits函数
这个函数可以使用位移和按位或运算符来构建出结果,从而返回所有奇数位设置为1的操作
Replacebyte函数
这个函数可以计算出需要进行位移的位数,然后分别创建一个用于清除和设置的掩码。最后,我们使用这些掩码对x进行操作,从而实现了替换字节的操作。
Rotateleft函数
这个函数可以使用位操作符 << 来实现左旋转操作。
Floatabsval函数
这个函数可以检查绝对值是否大于单精度浮点数表示的最大值,是,说明是NaN,直接返回原始值;不是返回绝对值。就可以实现返回浮点数绝对值的操作。
实验总结
在实验过程中,我们首先学习了整数和浮点数的二进制编码表示,了解了如何将十进制数转换为二进制数以及如何在计算机中存储和表示整数和浮点数。我们还学习了如何使用位操作来对二进制数进行操作,例如按位与、按位或、按位异或等。这些操作在计算机底层原理中非常重要,因为它们可以让我们更深入地理解计算机如何处理数据。我们通过实现一组给定功能的函数来加深对数据二进制编码表示的了解。这些函数包括加减乘除、位移运算、位操作等。在实现这些函数的过程中,我们不仅学会了如何使用位操作和算术运算来处理数据,还了解了不同类型的数据如何进行比较和运算。通过这次实验,我们不仅掌握了计算机中整数和浮点数的二进制编码表示,还学会了如何使用有限类型和数量的运算操作来实现一组给定功能的函数。这些知识和技能对我们今后的学习和工作都具有重要意义,因为它们可以帮助我们更好地理解计算机底层原理、编程和算法设计。
csapp的第一个实验,函数确实多一点,但是对于学习一些计算机系统的知识还是很有帮助的,希望这篇文章对你有所帮助,加油!