《深入理解计算机系统》实验一Data Lab

Posted 金石不渝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《深入理解计算机系统》实验一Data Lab相关的知识,希望对你有一定的参考价值。

实验一 数据表示与运算实验

一、实验目的

1.更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。
2. 加深对数据二进制编码表示的了解。
3. 使用有限类型和数量的运算操作实现一组给定功能的函数。

二、实验仪器设备/实验环境

1.Linux操作系统—64位 Ubuntu 18.04
2. C编译环境(gcc)
3. 计算机

三、实验内容

本实验每位学生拿到一个datalab-handout.tar文件。学生可以通过U盘、网盘、虚拟机共享文件等方式将其导入到Unbuntu实验环境中,选择合适位置存放。然后在Ubuntu环境下解压。解压后,根据文件中的叙述和要求更改bits.c文件,其他文件不要动。本次实验的主要操作方式为:使用C语言的位操作符实现题目要求。
需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。

1.位操作

表1列出了bits.c中一组操作和测试位组的函数。其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。
也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。

2.补码运算

表2列出了bits.c中一组使用整数的补码表示的函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。

3.浮点数操作

表3列出了bits.c中一组浮点数二进制表示的操作函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。注意输入参数和返回结果均为unsigned int类型,但应作为单精度浮点数解释其32 bit二进制表示对应的值。

四、实验步骤

  1. 使用dlc检查函数实现代码是否符合实验要求的编码规则。
    首先./dlc bits.c直接检测是否有错误。如图1.1所示:

    由图知,如果没有任何错误输出,则表示bits.c文件的编写无误,基本符合要求。
    然后用-e选项调用dlc,观察操作符数。如图1.2所示:
    通过此选项可以查看每一道具体题目是否符合要求。如果没有任何问题,输出结果如下图1.2所示。如果局部出现问题,则输出会类似于图1.3所示,在具体位置表示出相应题目的具体问题。对于本例,小题1:语法错误,小题3:超过了最多操作
    符数量要求,原题要求不超过3个,结果使用了5个。

在这里插入图片描述

  1. 使用 btest 检查函数实现代码的功能正确性。
    a) 首先使用make编译生成btest可执行程序,如图1.4所示。部分warning不需要特殊处理,但如果出现的warning过多则需要适当注意是否程序中有错误。


b) 然后调用 btest 命令检查 bits.c中所有函数的功能正确性。如图1.5所示,得分会以数字形式显示在左侧,错误显示则显示error。

五、实验注意事项

1.注意给出的可以使用的运算符及最大个数。
2.除了float类型的两个操作函数可以使用if-else条件语句外,其它函数只能用顺序结构进行代码设计和实现。
3.本实验使用btest程序进行评分时记分为50分制,但最后教师端进行实际成绩核算时会使用100分制(乘以2)。

答案:

isZero

判断变量x是否为0。如果为0,则返回1;否则,返回0。

/*
 * isZero - returns 1 if x == 0, and 0 otherwise 
 *   Examples: isZero(5) = 0, isZero(0) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int isZero(int x) 
/*
  没啥好说的。x^0。
  x=0时,x^0=0。
  x!=0时,x^0=1。
  在取非(!)
*/
  return !(x^0);


negate

将输入参数x的值取相反数,返回-x。

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) 
/*
  没啥好说的。
  补码与原码取反加1
*/
  return ~x + 1;


specialBits

构建0xffca3fff,并返回。

/* 
 * specialBits - return bit pattern 0xffca3fff
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 3
 *   Rating: 1
 */
int specialBits(void) 
/*
  因int取值为0~255,
  刚开始的思路是创建两个变量,使用位移构造出ca3。
  0xff...fff肯定是要取反获得的了,所以刚开始就构造0xca3的反码0x35c,
  在位移使(0x0035c000),取反即完成。
  所以可得(~((0x35<<16)|(0xc0<<8))=0xffca3fff。
  发现使用了4op,不合题意。

  分析有没有可以优化的,
  取反~占1op,构造0x35c"要对0x35使用位移1op,合并成0x35,0xc也要1op,位移到正确的位置1op。
  想到能不能使用加法来构造0x35c这样位移+合并的2op就变成加法的1op。
  发现int+int到不了0x35c,不过这是一个很好的思路,用其他的办法来构造0x35c
  0x35c二进制为0011 0101 1100,发现低2位和高2位都是0,可以吧0x35c>>2=1101 0111=0xD7
  所以0x35c可以表示为0xD7<<2,很好,在把0x35c位移到合适的位置,即
  0xD7<<2<<12=0xD7<<14
  取反即~(0XD7<<14)返回0xffca3fff

*/
  //0xD7<<2<<12, D7<<2 = 35c,
  return ~(0XD7<<14);


upperBits

根据输入的变量n,构建一个高n位为1其他位为0的数,并返回该值。注:0<= n <=32

/* 
 * upperBits - pads n upper bits with 1's
 *  You may assume 0 <= n <= 32
 *  Example: upperBits(4) = 0xF0000000
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 10
 *  Rating: 1
 */
int upperBits(int n) 
/*
  只需考虑0和非0的情况
  因高位填充1的数量是不可控的,所以要用>>算术右移来控制。
  当n=0时高位为0,当n=!0时高位为1,这样>>都可以满足,
  使用两次!!n即可满足。
  吧!!n放到最高位右移,右移此时为n-1次即可完成。因不能使用加法,只能采取+(-1),而0取反为-1。
  构造出(!!n<<31)>>(n+(~0))

*/
  return (!!n<<31)>>(n+(~0));


bitMatch

构建一个比特序列(int型),构成规则如下:如果x和y在某一个bit位置的值相同,则此序列的相应位置为1,否则该位置值为0。

/* 
 * bitMatch - Create mask indicating which bits in x match those in y
 *            using only ~ and & 
 *   Example: bitMatch(0x7, 0xE) = 0x6
 *   Legal ops: ~ & |
 *   Max ops: 14
 *   Rating: 1
 */
int bitMatch(int x, int y) 
/*
  根据题目要求和使用3种运算符,暴力写,加上一丢丢经验
  取
  x=0101, y=0110  相同位码为1100
  ~x=1010,~y=1001
  让他们碰一碰
  x&y=0100,~x&~y=1000
  写到这里就写出来了
  (x&y) | (~x&~y)。

  如果不行的话就去碰~x&y x&~y。
  
*/  
  return (x&y) | (~x&~y);


bitOr

计算按比特或(x | y),并将计算结果返回。

/* 
 * bitOr - x|y using only ~ and & 
 *   Example: bitOr(6, 5) = 7
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitOr(int x, int y) 
/*
  根据题目要求和使用2种运算符,和上题一样暴力写,加上一丢丢经验
  取
  x=0101, y=0110  。x|y=0111
  ~x=1010,~y=1001
  让他们碰一碰
  ~x&~y=1000。(一般这种情况不会使用到x和y的原数据)
  写到这里就写出来了
  ~(~x&~y)
  
*/  
  return ~(~x&~y);


absVal

计算变量x的绝对值,并将其绝对值返回。

/* 
 * absVal - absolute value of x
 *   Example: absVal(-1) = 1.
 *   You may assume -TMax <= x <= TMax
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 4
 */
int absVal(int x) 
/*
  第一反应先对x取反+1,求x的负数即(~x+1),完成了对负数的绝对值,
  但此时正数变成了负数,不满足。
  找能不能使用x来使得正数变负数后用x经过一系列操作变成正数的操作Z,且负数变成正数经过操作Z还是保持不变。
  后来发现是不行了,即此输出是可能当输入的。

  负数和正数的区别在与最高位的1/0,可使用^1或^0,来得到负数的取反操作且正数保持不变。
  取反已完成,还剩下一个+1操作。此+1操作要使负数才+1而正数是+0。
  利用它们的区别,负数最高为1,正数最高为0.
  ~1+1=0+1=1,~0+1。
  我们可以使用溢出来完成。
  即(~(x>>31)+1)。当负数时~(0xffffffff)+1=1,当正数时~(0x00000000)+1=0(溢出)。

  如果可以用"-"op的话可以直接-(x>>31)

*/
  return (x^(x>>31))+(~(x>>31)+1);


logicalNeg

使用位操作符实现逻辑非(!x)操作,并将取逻辑非之后的结果返回。

/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int logicalNeg(int x) 
/*
  仔细观察,!0=1,!非0的数就是1。而我们不知道x具体的位数,而且不能使用循环判断。
  可以利用补码与原码来进行判断,x|(~x+1)。因为x|(~x)=11...11,不能区分0,所以使用补码x|(~x+1)。
  这样,
  如果是非零数,经过x|(~x+1),最高位一定是1
  如果是0,经过x|(~x+1),最高位是0
  利用溢出,((x|(~x+1))>>31)+1即完成。
 
 */
  return ((x|(~x+1))>>31)+1;


bitParity

如果x中包含奇数个0,则返回1;否则返回0。

/*
 * bitParity - returns 1 if x contains an odd number of 0's
 *   Examples: bitParity(5) = 0, bitParity(7) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int bitParity(int x) 
/*
  奇数个0和奇数个1是一样的意思。
  奇数个1返回1,否则返回0。
  用^。1^1^1返回1,1^0^1返回0,
  也就是有奇数个1^时返回1,偶数个1^时返回0。
  利用这一特性,
  把高16位和低16位^,然后在拿结果高8位和低8位^.....高1位和低1位^,最后得出最高位的一个数。
  利用特性,把最高位右移到最低位 >>31,两次!,即可得出结果
  
  :思路来源于百度,留下了没技术的泪水。
*/
  x=x^(x<<16);
  x=x^(x<<8);
  x=x^(x<<4);
  x=x^(x<<2);
  x=x^(x<<1);
  return !!(x>>31);


byteSwap

将x的第n字节和第m字节交换,0 <= n <= 3, 0 <= m <= 3,然后将交换后的值返回。

/* 
 * byteSwap - swaps the nth byte and the mth byte
 *  Examples: byteSwap(0x12345678, 1, 3) = 0x56341278
 *            byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
 *  You may assume that 0 <= n <= 3, 0 <= m <= 3
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 25
 *  Rating: 2
 */
int byteSwap(int x, int n, int m) 
/*
    先把n、m处的字节提取出来成a、b。n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。&0xff只取低8位
    在把a、b扩位到它要放入的位成am、bn
    在把x处的n、m字节重置为0,利用y+(~y+1)(补码)=0的性质,成bm、an,bm&an即x处的n、m字节重置为0
    在把它们结合起来成bn|am|(an&bm),即完成。

    :可把n<<3,m<<3用变量存储。但是不利于阅读。
    用了好多个op...。刚开始刚好用了25个op,好巧。

    2.0:
    写下面的replaceByte(int x, int n, int c)时,
    发现可以使用x&~(0xff<<(n<<3))来使n字节变成0。
    于是
    int bm = x+(~(b<<(m<<3))+1)
    int an = x+(~(a<<(n<<3))+1)
    可以替换成int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)))节省了op
*/

    int a = (x>>(n<<3))&0xff;   
    int b = (x>>(m<<3))&0xff;   
    int am = a<<(m<<3);
    int bn = b<<(n<<3);

    int mask = x&~((0xff<<(n<<3)|0xff<<(m<<3)));

    //int bm = x+(~(b<<(m<<3))+1);
    //int an = x+(~(a<<(n<<3))+1);

    return bn|am|mask;


getByte

提取x的第n个字节。0 <= n <= 3 (0代表最最低为字节,3代表最高位字节),并将其返回。

/* 
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (least significant) to 3 (most significant)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) 
/*
  在byteSwap(int x,int n,int m)函数中已经实现了此操作。
  n<<3=n*8,是因为1字节=8位,要定位到n字节就*8。
  &0xff只取低8位
*/
  return (x>>(n<<3))&0xff;


isGreater

如果x > y,则返回1,否则返回0。

/* 
 * isGreater - if x > y  then return 1, else return 0 
 *   Example: isGreater(4,5) = 0, isGreater(5,4) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isGreater(int x, int y) 
/*
  这题好难,回过头来看草稿。写出来只能满足大部分数,
  当遇到0x7fffffff、0x80000000、0x80000001数是总是不符合要求。

  上百度上找到了答案改了一下

  1.正数比负数大
  2.负数比正数小
  3.两数相减为正数时返回1
  4.相等返回0

  (!a&b)|!c:
  x是正数,y是负数,返回1。x是正数,y是正数,则看后面的相减是否为正数(!c),为正返回1。
  x是负数,y是正数,返回0。x是负数,y是负数,则看后面的相减是否为正数(!c),为正返回1。
  写(!a&b)|!c还不够,
  还要防止x-y的溢出,使负数变成正数0x80000000-0x7fffffff=0x80000000+0x80000001=0x00000001,
  产生错误的返回结果。
  (!a) | b):只要y为负或x为正即可。
  判断相等返回0:!!(x ^ y)
  合并即return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);
*/
  int a = (x>>31),b=(y>>31);
  int sub = x + (~y+1);
  int c = (sub>>31);
  return (( (!a)&b) | !c) & ( (!a) | b) & !!(x ^ y);


isNegative

如果x < 0,返回1;否则返回0。

/* 
 * isNegative - return 1 if x < 0, return 0 otherwise 
 *   Example: isNegative(-1) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int isNegative(int x) 
/*
  依题意,负数返回1。其他返回0
  负数就是最高位为1。
  让x>>31最高位变成最低位再^0xf>>31如果等于0说明x是负数,!!取0
  即(x>>31^0xf>>31),如果不等于0说明x是非负,!!取1
  即!!((x>>31)^0xf>>31)

  想了想,^0xf>>31有点复杂,可以直接~(x>>31),
  如果x是负数(最高位为1)此时就等于0
  如果x是正数和0(最高位为0)此时就等于1
  在取!即可
  即!~(x>>31)

*/
  return !~(x>>31);


isPower2

如果x是2的整数次幂,则返回1;否则返回0。

/*
 * isPower2 - returns 1 if x is a power of 2, and 0 otherwise
 *   Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
 *   Note that no negative number is a power of 2.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int isPower2(int x) 
/*
  每个数在二进制中都是唯一的。
  也就是2的幂,在二进制中只有一位是1其他全是0才有可能是2的幂(除了第一位是1不是2的幂)
  即可以用x&(x-1)来判断,如果只有一个1返回0,加个!,
  !(x&(x+(~0)))。
  还要判断是不是负数,是负数就返回0(!!~(x>>31)
  还要判断是不是0,是0也要返回0!!x
  合并起来就是
  (!!~(x>>31) & !(x & (x + (~0)))) & !!x
*/
  return (!!~(x>>31) & !(x & (x + (~0)))) & !!x;


addOK

如果x+y没有溢出,则返回1;否则返回0。

/* 
 * addOK - Determine if can compute x+y without overflow
 *   Example: addOK(0x80000000,0x80000000) = 0,
 *            addOK(0x80000000,0x70000000) = 1, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int addOK(int x, int y) 
/*
  依课本P65页给出的条件:
  令s=x+y
  当且仅当x>0,y>0,但s<=0时,计算s发生了正溢出
  当且仅当x<0,y<0,但s>=0时,计算s发生了负溢出

  参考练习题2.30写出
  int sum=x+y;
  int nag_over = x>>31 & y>>31 & ((!(sum>>31))|(!sum));
  int pos_over = !(x>>31) & !(y>>31) & sum>>31;  
  return !nag_over & !pos_over;

  改进:
  发现条件可以概括为:x和y符号位相同,且x和sum符号位不同时,发生了溢出。

*/
  int sum=x+y;

  return !((!(x>>31 ^ y>>31)) & (x>>31 ^ sum>>31));


subtractionOK

如果x-y没有溢出,则返回1;否则返回0。

/* 
 * subtractionOK - Determine if can compute x-y without overflow
 *   Example: subtractionOK(0x80000000,0x80000000) = 1,
 *            subtractionOK(0x80000000,0x70000000) = 0, 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int subtractionOK(int x, int y) 
/*
  参考addOK函数
  int sum = x+(~y+1)  //x-y
  条件为:x和y符号位不同,且x和sum符号位不同时,发生了溢出。
*/  
  int sum=x+(~y+1);

  return !((x>>31 ^ y>>31) & (x>>31 ^ sum>>31));


oddBits

返回一个32bit数,这数的所有第奇数个bit位置的值为1。

/* 
 * oddBits - return word with all odd-numbered bits set to 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 2
 */
int oddBits(void) 
  //构造掩码1010(0xa)即可
  return (0xaa) + (0xaa<<8) + (0xaa<<16) + (0xaa<<24);


replaceByte

将x的第n个字节用 c 进行替换,0 <= n <= 3, 0 <= c <= 255 并将替换后的结果返回。

/* 
 * replaceByte(x,n,c) - Replace byte n in x with c
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
 *   You can assume 0 <= n <= 3 and 0 <= c <= 255
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 3
 */
int replaceByte(int x, int n, int c) 
/*
  把c移位到它要放入的字节。
  创建源码使x在c字节处为0。
  两者取|
*/
  int a = c<<(n<<3);
  int mask = x&~(0xff<<(n<<3));
  return a|mask;


rotateLeft

将x向左循环移位n个bit。循环移位是指左边移除去的比特自动填充到右边空出的位置上。0 <= n <= 31,并将循环移位后的值返回

/* 
 * rotateLeft - Rotate x to the left by n
 *   Can assume that 0 <= n <= 31
 *   Examples: rotateLeft(0x87654321,4) = 0x76543218
 *   Legal ops: ~ & ^ | + << >> !
 *   Max ops: 25
 *   Rating: 3 
 */
int rotateLeft(int x, int n) 
/*
  创建一个掩码把n高位获取出来 (x & ((1<<n)-1))是取低n位,
  利用取反+左移改成取高位((x & ~((1<<(32-n))-1))>>(32-n))

  最高位为1时,右取高位会有点小问题,右移产生了1。再创建一个掩码,来使最高位为1时右移所产生的1变成0
  创建一个掩码,低n位为1,使用&就可以把右移所产生的1变成0
  掩码为:~(((1<<(32-n))-1)<<n)
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n),获取了高位

  获取32-n位,在左移n位,空出位置来放n高位
  即:(x& ((1<<(32-n))-1))<<n)

  在把 获取到的高位 | (x& ((1<<(32-n))-1))<<n) 即可
  即:((x& ((1<<(32-n))-1))<<n) | (((x & ~((1<<(32-n))-1))>>(32-n)) & ~(((1<<(32-n))-1)<<n))
----------------------

  :有一个有趣的。创建一个掩码,低n位为1
  可以用这个操作来进行代替。
  掩码:(0 | ((1<<n)-1))。即构建一个低n位为1的数,
  即:((x & ~((1<<(32-n))-1))>>(32-n)) & (0 | ((1<<n)-1)),获取了n高位
  正常来说是没问题的,但是在当n=0时,程序就出现了错误(0 | ((1<<0)-1))=0,&0肯定为0

  所以还是用上面的操作。
*/
  int nag_1 = ~0;
  int sub_n = 32+(~n+1);
  int get_exc_hight_n_bit=(1<<sub_n)+nag_1;
  return ((x& (get_exc_hight_n_bit))<<n) | 
(((x & ~(get_exc_hight_n_bit))>>(sub_n)) & ~((get_exc_hight_n_bit)<<n));


floatAbsVal

通过bit级操作返回一个float型浮点数的绝对值。如果输入参数为NaN,则直接返回输入参数的原值。

/* 
 * floatAbsVal - Return bit-level equivalent of absolute value of f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument..
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned floatAbsVal(unsigned uf) 
/*
  根据课本P78给出浮点表示格式
  最高位为符号位s,负数(s=1)和正数(s=0)
  取绝对值只要把符号位置为0,x=uf&0x7fffffff   (没有大小限制了真好)
  NaN的表示为s11111111(经过上面的符号位改变,此时s=0) 其他位不为0
  只要x比011111111(0x7f8)大说明x为NaN
*/
  int x=uf&0x7fffffff;
  if(x>0x7f800000)
    return uf;
  else
    return x;


floatIsEqual

判断两个浮点数是否相等,如果相等则返回1,否则返回0。
如果输入参数中含有NaN,则返回0。
注:+0和-0被当作相等的情况对待。

/* 
 * floatIsEqual - Compute f == g for floating point arguments f and g.
 *   Both the arguments are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   If either argument is NaN, return 0.
 *   +0 and -0 are considered equal.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 25
 *   Rating: 2
 */
int floatIsEqual(unsigned uf, unsigned ug) 
/*
  先来一手uf==ug试试水。
  哦豁果然不行,挂在0和(0x80000000)。
  那就判断uf和ug是不是0和0x80000000。
  还要判断是不是NaN。判断符号位对应的NaN
  上面所有都不是的话,那就直接到uf==ug就好了
*/

    int min = 0x80000000;

    if((uf==0 && ug==min) || (uf==min && ug==0) || (uf==min && ug==min))
      return 1;

    if(uf&0x80000000)
      if(uf>0xff800000)
        return 0;
      
    else if(uf>0x7f800000)
      return 0;
    
    
    if(ug&0x80000000)
      if(ug>0xff800000)
        return 0;
      
    else if(ug>0x7f800000)
      return 0;
    
    
    return uf == ug;


总结全部题型

/* 
 * CS:APP Data Lab 
 * 
 * <Please put your name and userid here>
 * 
 * bits.c - Source file with your solutions to the Lab.
 *          This is the file you will hand in to your instructor.
 *
 * WARNING: Do not include the <stdio.h> header; it confuses the dlc
 * compiler. You can still use printf for debugging without including
 * <stdio.h>, although you might get a compiler warning. In general,
 * it's not good practice to ignore compiler warnings, but in this
 * case it's OK.  
 */

#if 0
/*
 * Instructions to Students:
 *
 * STEP 1: Read the following instructions carefully.
 */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.

INTEGER CODING RULES:
 
  Replace the "return" statement in each function with one
  or more lines of C code that implements the function. Your code 
  must conform to the following style:
 
  int Funct(arg1, arg2, ...) 
      /* brief description of how your implementation works */
      int var1 = Expr1;
      ...
      int varM = ExprM;

      varJ = ExprJ;
      ...
      varN = ExprN;
      return ExprR;
  

  Each "Expr" is an expression using ONLY the following:
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>
    
  Some of the problems restrict the set of allowed operators even further.
  Each "Expr" may consist of multiple operators. You are not restricted to
  one operator per line.

  You are expressly forbidden to:
  1. Use any control constructs such as if, do, while, for, switch, etc.
  2. Define or use any macros.
  3. Define any additional functions in this file.
  4. Call any functions.
  5. Use any other operations, such as &&, ||, -, or ?:
  6. Use any form of casting.
  7. Use any data type other than int.  This implies that you
     cannot use arrays, structs, or unions.

 
  You may assume that your machine:
  1. Uses 2s complement, 32-bit representations of integers.
  2. Performs right shifts arithmetically.
  3. Has unpredictable behavior when shifting if the shift amount
     is less than 0 or greater than 31.


EXAMPLES OF ACCEPTABLE CODING STYLE:
  /*
   * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
   */
  int pow2plus1(int x) 
     /* exploit ability of shifts to compute powers of 2 */
     return (1 << x) + 1;
  

  /*
   * pow2plus4 - returns 2^x + 4, where 0 <

以上是关于《深入理解计算机系统》实验一Data Lab的主要内容,如果未能解决你的问题,请参考以下文章

深入理解计算机系统 (CS:APP) - 高速缓存实验 Cache Lab 解析

2021哈工大深入理解计算机系统Lab5(linklab)

深入理解计算机系统 (CS:APP) Lab2 - Bomb Lab 解析

Lab2-深入理解系统调用

Lab2-深入理解系统调用

CSAPP实验一:位操作(Data Lab)