csapp lab环境搭建及lab1wp

一.环境搭建

**

首先要搞一个ubantu的虚拟机,具体自行百度
搞好虚拟机开始搭建环境,右键打开终端,然后输入以下指令

apt-get update    //更新apt软件源
apt-get install sudo   //安装sudo
sudo apt-get install build-essential  //安装c/c++编译环境
sudo apt-get install gcc-multilib  //补充gcc的完整环境(gcc-multilib)
sudo apt-get install gdb  //安装gdb
sudo apt-get install make  //安装make

如何做题及如何检查对错,输入以下指令(以第一道题bitXor为例)

make btest
./btest -f bitXor
./btest -g //总览所有题的得分

在这里插入图片描述
得满分就说明做对了
**

二.lab1wp

int规则(百度翻译的,应该能看懂)

整数常量0到255(0xFF),包括在内。
不允许使用大常量,例如0xffffffff。
明确禁止您:

1.使用任何控件构造,例如if、do、while、for、switch等。

2.定义或使用任何宏。

3.在此文件中定义任何附加功能。

4.调用任何函数。

5.使用任何其他操作,如&&、| |、-、or、?:

6.使用任何形式的铸造。

7.使用int以外的任何数据类型。这意味着
无法使用数组、结构或联合。

1.bitxor

//1
/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */

题意就是用~、&来实现异或
~:对于二进制的每一位,将1变为0,将0变为1

对于x,y,只能有两种&组合,x&y和~x & ~y,如果是 ~x&y,或者是 ~y&x,都是行不通,要么都取反,要么都不取
这里就用4,5来尝试一下,4&5=0100,~4 & ~5=1010
这下就是进行不断尝试组合,出答案

int bitXor(int x, int y) {
    return ~(x & y)&~(~x&~y);
}

2.tmin

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */

题意是求二进制补码的最小值,0x10000000是最小值,但是只能输入0到255(0xFF)之间的,所以要用到左移<<,具体如下:

int tmin(void) {
    return 1 << 31;
}

3.isTmax

//2
/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */

题意是如果接受的x为二进制最大值,就返回1,否则为0
二进制最大值为0x7FFF FFFF,假设它就是x,则x+1就是0x8000 0000,这个时候将二者异或就得到了0xFFFF FFFF,再加一个 ‘~’ ,就得到了0,最后return时再用逻辑非即可。但是0xFFFF FFFF与其+1异或后也是0xFFFF FFFF,这个时候再对其+1的数两次 ‘!’,为0,结合一下进行与运算
具体实现如下:

int isTmax(int x) {
    int r=x+1;
    r=~(x^r);
    return !(r^x) &!!(x+1);   
}

4.allOddBits

/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */

题意就是当所有奇数位为1时,返回1。
满足所有奇数位为1的数只有0xAAAA AAAA和0xFFFF FFFF,这个时候就要用到异或来判断了
首先假设x是0xAAAA AAAA,要弄出一个与x异或的值0xAAAA AAAA,这样使其为0后,再用逻辑非变成1,
如果x为0xFFFF FFFF ,这里需要再多加一条与运算,使其先变为0xAAAA AAAA再异或就得到0了
现在还有一个问题就是0xAAAA AAAA怎么给变量赋上值,这里就要用到逻辑左移和异或结合得到
具体如下:

int allOddBits(int x) {
    int q1=0xaa;
    int q2=q1<<8;  //q2=aa00
    int q3=q2^q1;  //q3=aaaa
    int q4=q3<<16; //q4=aaaa0000
    int q=q3^q4;  // q=aaaaaaaa
    q1=q&x; 
    return !(q1^q);
}

5.negate

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */

题意就是取相反值
这个还是要用到~,对每一位,0变1,1变0
就拿x=0xFFFF FFFF来说,~x=0,0+1=1,
再拿x=0x8000 0001来说,~x+1=0x7FFF FFFD +1=0x7FFF FFFF
具体如下:

int negate(int x) {
  return ~x + 1;  
}

6.isAsciiDigit

/* 
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */

题意就是如果0x30 <= x <= 0x39,则返回为1
也就是满足x-0x30>=0&&x-0x39<=0返回为1
这里x-0x39>=0要改为x-0x3a<0好表示,当然也可以0x39-x>0
然后结合逻辑非’!'以及或运算
具体如下:

int isAsciiDigit(int x) {
      
      return !(((x+~0x30+1)>>31)|!((x+~0x3a+1)>>31));             
}

7.conditional

/* 
 * conditional - same as x ? y : z
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */

题意就是实现x?y:z即如果x为真 那么值就是y 否则就是z
先将用两个逻辑非将不为0的变为1,为0的则还是0
若x为真,则将其变为x=0xFFFF FFFF,这样有利于与运算时
若不为真,则使用逻辑取反,将x=0变为0xFFFF FFFF
具体如下:

int conditional(int x, int y, int z) {
   x=!!x; //先将x化为0或1
   int a=(x<<31)>>31;
   return (a & y)+(~a&z);
}

8.isLessOrEqual

/*

  • isLessOrEqual - if x <= y then return 1, else return 0
  • Example: isLessOrEqual(4,5) = 1.
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 24
  • Rating: 3
    */
    题意:若x<=y返回为1,否则为0
    首先先用异或和逻辑非判断x与y是否相等,相等则为1

若不相等,则x为负数,y为正数时,也就是x符号位为1,y的符号位为0时,我们可以试图让其返回为1
那先让x,y同时右移31为,此时x为0xFFFF FFFF,y为0,用逻辑非让x为0,再用或运算使x,y两者返回为0,
最后再用一个逻辑非让其为1。其实考虑的这种方法虽然只考虑了x为负数,y为正数,但是也同样适用y为负数,x为正数的时候

然后再考虑x与y符号位一致时,首先用异或判定符号位是否一致,然后此时只需用x+~y+1=x-y得到的数为0xFFFF FFFF,使用两个逻辑非将其变成1,然后给两者与运算

满足以上三种情况的任意一种就可以
具体如下:

int isLessOrEqual(int x, int y) {
    int equal= !(x^y);
     
    int xh=x>>31;
    int yh=y>>31;
    int wudi=!((!xh)|yh);

    int yf=~y+1;
    int same=!(xh^yh);
    int jian=!!((x+yf)>>31);
    return equal|wudi|(same&jian);	
}

9.logicalNeg

/* 
 * 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 
 */

题意:用上述的符号实现逻辑非
让不为0的数变为0,让0变为1,想一想,0和他的相反数符号位都是0,而相反不为0的数和他的相反数符号位肯定有一个为1
使用或运算得到-1最后再加上个1就满足了
具体如下:

int logicalNeg(int x) {
     int xfh=(~x+1)>>31;  
     int xh=x>>31; 
     return (xh | xfh)+1; 
}

10.howManyBits

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */

题意:判断输入的数有几位
首先我们要对负数进行取反,正数该是什么就是什么,主要是为了方便判断位数
这里要用到二分法,先判断是否有16位
如果有,再判断是否有24位,否则就判断是否有8位,然后像这样8,4,2,1,0进行判断
这里咱也不会讲,就直接上代码吧

int howManyBits(int x) {
   int sign = x >> 31;
   x = (~sign & x) | (sign & ~x); //取反
   int b16 = !!(x >> 16) << 4;//判断是否有16位
   x >>= b16;

   int b8 = !!(x >> 8) << 3; 
   x >>= b8;

  int b4 = !!(x >> 4) << 2;
  x >>= b4;

  int b2 = !!(x >> 2) << 1; 
  x >>= b2;

  int b1 = !!(x >> 1);
  x >>= b1;

  int b0 = x;
  return b16 + b8 + b4 + b2 + b1 + b0 + 1;//+1是因为就如果像0这样的数,判定的时候是有1位的
}

float规则

编码规则没有那么严格。您可以使用循环和

条件控制。您可以同时使用整数和无符号。

可以使用任意整数和无符号常量。你可以使用任何算术,

对整型或无符号数据执行逻辑或比较操作。

明确禁止您:

1.定义或使用任何宏。

2.在此文件中定义任何附加函数。

3.调用任何函数。

4.使用任何形式的铸造。

5.使用除int或unsigned之外的任何数据类型。这意味着你

无法使用数组、结构或联合。

6.使用任何浮点数据类型、运算或常量。

floatScale2

/*

*floatScale2-返回表达式2*f的等效位级别

*浮点参数f。

*参数和结果都作为无符号int传递,但是它们将被解释为单精度浮点值。

*当参数为NaN时,返回参数

*合法运算:任何整数/无符号运算,包括| |,&&&。如果,虽然

*最多操作符:30

*评级:4

*/

在这里插入图片描述
这张图片有点比较模糊,也请大家凑和看吧
第一位是符号位,中间的8位是阶码,后面的23位是尾数
s是符号位,M是尾数,E是阶码
浮点数就分为这四类,规格化的是中间八位!=0&!=255,后面任意
非规格化的就是中间八位为0,后面任意值
无穷大就是中间八位为0xFF,后面23位为0
NaN跟无穷大的区别就是后面23位不为0

题意:返回传入的数的二倍
无穷大和NaN返回值就是它本身
规格化的就让它阶码+1就可以了,非规格化的就让它左移一位(比如二进制10左移就是100)

代码实现如下:

unsigned floatScale2(unsigned uf) {
      unsigned exp=(uf&0x7f800000)>>23;
      unsigned sign=uf>>31&0x1;
      unsigned frac=uf&0x7FFFFF;
      unsigned res;
  
    	if(exp==0xff){
     	return uf;
   	}
  	else if(exp==0){
   	 frac<<=1;//
   	 res=(sign<<31)|(exp<<23)|frac;
 	 }
 	 else{
   	 exp++;
   	 res=(sign<<31)|(exp<<23)|frac;
 	 }
  return res;
}

floatFloat2Int

/*

*float2int-返回表达式(int)f的位级等效值

*对于浮点参数f。

*参数作为无符号int传递,但它将被解释为单精度浮点值。

*任何超出范围的东西(包括NaN和infinity)都应该返回

*0x80000000u。

*合法运算:任何整数/无符号运算,包括||,&&. also if, while

*最多符号位:30

*评级:4

*/

题意:将浮点型uf转换为int类型
不会了。。。
不理解23和31是怎么回事。。。
只有搬来的代码

int e = ((uf & 0x7F800000) >> 23) - 0x7F;
    int f = ((uf & 0x007FFFFF) | 0x00800000);

    if (!(uf & 0x7FFFFFFF) || e < 0)
        return 0;
    if (e > 31)
        return 0x80000000;

    if (e > 23)
        f = f << (e - 23);
    else
        f = f >> (23 - e);

    if (!(uf >> 31))
        return f;
    else
        return ~f + 1;

floatPower2

/*

*floatPower2-返回与表达式2.0^x等效的位级别

*(2.0升为x的幂)用于任何32位整数x。

*返回的无符号值应具有相同的位

*表示为单精度浮点数2.0^x。

*如果结果太小,无法表示为denorm,则返回0. 如果太大,返回+INF。

*合法运算:任何整数/无符号运算,包括| |,&&&。如果,虽然

*最多:30

*评级:4

*/

fw继续摆烂
搬运代码如下:

if(x>127)//overflow
      return 0x7f800000;//+inf 符号位0 阶码全1 尾数全0
 
    //规格化的 [-126,127]
    if(x>=-126)
    {
      unsigned exp = x+127;//加上bias
      return exp<<23;//只需改变阶数
    }
 
    //非规格化的 [-149,-127]
    if(x>=-149)
      return 0x1<<(x+149);//只需改变尾数
 
    //x<-149 too small to be represented
    return 0;
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值