csapp环境配置与实验一

环境配置

  • 安装gcc库
yum install glibc-devel.i686
  • 报错,在vs中安装c/c++拓展

在这里插入图片描述

在这里插入图片描述

  • 再次安装,成功

在这里插入图片描述

函数实现

bitXor

/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
  //x^y=(~x&y)|(x&~y)
  //=~(~(~x&y)&~(x&~y))
  //4=1000,5=1001,德摩根定律
  return ~(~(~x&y)&~(x&~y));
}

tmin

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  //返回最小补码值 0x8000 0000
  return 1<<31;
}

ifTmax

/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x)
{
  //判断是否是最大补码 最大补码为0x7fffffff
  //按位异或,取非,全0输出1
  int y = x+1;
  y=x+y;
  y=~y;
  y=!y;
  return y&!!(~x);//排除x全1
}

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
 */
int allOddBits(int x) {
  //所有奇数位取1返回1
  return !((x&0xAAAAAAAA)^0xAAAAAAAA);
}

检查语法不通过

在这里插入图片描述

要求只能使用0x0 - 0xff的常量

./dlc权限不够 赋予权限

chmod 777 dlc
/* 
 * 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
 */
int allOddBits(int x) {
  //所有奇数位取1返回1(从0开始)
  //x先与0xAAAAAAAA按位与,再与0xAAAAAAAA异或,最后取非
  //通过0xAA左移
  int y = 0xAA;
  y = y + (y<<8);
  y = y + (y<<16);
  return !((x&y)^y);
}

negate

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

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
 */
int isAsciiDigit(int x)
{
  //判断输入值是否是0-9的ASCII值
  //0x30 <= x <= 0x39
  //在0x03与0x39之间的数与0x30和0x39+1分别作差符号位必定相反,相同输出0
  //右移保持符号位不变!
  return !((x + ~0x30 + 1) >> 31) ^ !((x + ~0x3A + 1) >> 31);
}

conditional

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

isLessOrEqual

/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y)
{
  int dValue = y + ~x + 1;      //y-x
  int dSign = dValue >> 31 & 1; //y-x符号
  int sign = 1 << 31;
  int xSign = ((x & sign) >> 31) & 1;
  int ySign = ((y & sign) >> 31) & 1;
  int bitXor = xSign ^ ySign;
  return (bitXor & xSign) | ((!bitXor) & (!dSign));
}

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 
 */
int logicalNeg(int x)
{
  //逻辑非
  //全0返回1  所以要找到0
  //0的符号位与0的补码的的符号位 或 的结果为0
  //其余的所有二进制数 符号位或的结果为1
  //最小值的补码为他本身,所以或的结果为1
  //其余数符号位相反,或的结果也为1
  return ((x >> 31) | ((~x + 1) >> 31)) + 1;
}

image-20201024102336756

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
 */
int howManyBits(int x)
{
  //返回在补码中能够代表x所需的最小位数
  int b16, b8, b4, b2, b1, b0;
  int mask = x >> 31;
  x = (mask & ~x) | (~mask & x); //如果为正数,保持不变;如果为负数,按位取反

  //step1:判断高16为是否有1
  b16 = !!(x >> 16) << 4; //如果高16为有1,则b16 = 16,否则为0
  x >>= b16;              //如果高16为有1,x右移16位舍弃低16位,在新的低16位继续查找;否则保持不变
  //step2:判断高8位是否有1
  b8 = !!(x >> 8) << 3;
  x >>= b8;
  //step3:高4位
  b4 = !!(x >> 4) << 2;
  x >>= b4;
  //step4:高2位
  b2 = !!(x >> 2) << 1;
  x >>= b2;
  //step5:高1位
  b1 = !!(x >> 1);
  x >>= b1;
  //step6:低1位
  b0 = x;

  return b16 + b8 + b4 + b2 + b1 + b0 + 1;
}

floatScale2

c语言中的编码方式:单精度浮点格式(float) —— s、exp和frac字段分别为1位、k = 8位和n = 23位,得到一个32位表示
V = ( − 1 ) s × M × 2 E V=(−1)^s×M×2^E V=(1)s×M×2E
尾数( significand)M是一个二进制小数;

阶码( exponent)E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。将浮点数的位表示划分为三个字段,分别对这些值进行编码:

一个单独的符号位s直接编码符号s

k位的阶码字段E
e x p = e k − 1 ⋯ e 1 e 0 exp = {e_{k - 1}} \cdots{e_1}{e_0} exp=ek1e1e0
n位的小数字段M
f r a c = f n − 1 ⋯ f 1 f 0 frac = {f_{n - 1}} \cdots {f_1}{f_0} frac=fn1f1f0

//float
/* 
 * floatScale2 - Return bit-level equivalent of expression 2*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 representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned floatScale2(unsigned uf)
{
  //用无符号整数来表示单精度浮点数(float总是带符号的)
  //IEEE 754-1985规定 用指数部分全为1,小数部分非0表示NaN
  int exp = (uf & 0x7f800000) >> 23; //取出指数部分
  int sign = uf & (1 << 31);         //取出符号位
  if (exp == 255)
    return uf;
  if (exp == 0)
    return uf << 1 | sign;
  ++exp;
  if (exp == 255)
    return 0x7f800000 | sign;           //exp+1 = uf * 2 返回无穷大
  return exp << 23 | (0x807fffff & uf); //否则返回常规uf*2
}

floatFloat2Int

/* 
 * floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
int floatFloat2Int(unsigned uf)
{
  //阶码的值:E = e - Bias(127)
  //尾数的值:M = 1 + frac(隐式编码法,隐含的1)
  //1 <= M <= 2
  //uf为无符号整数,将其强制转换为单精度浮点数
  //1. 规格化的值
  int sign = (uf >> 31) & 1;
  int exp = (uf >> 23) & 0xff;
  int frac = uf & 0x7fffff;
  int E = exp - 127;
  if (E < 0)
  {
    return 0;
  }
  //E>=31时,1.frac*2^E次方加一个符号位,超出int范围
  else if (E >= 31)
  {
    return 0x80000000u;
  }
  else
  {
    frac = frac | (1 << 23); //加上隐含的1
    if (E < 23)              //需要舍弃frac中部分位
    {
      frac = frac >> (23 - E);
    }
    else //不需要舍弃部分位
    {
      frac = frac << (E - 23);
    }
  }
  if (sign)
  {
    return -frac;
  }
  else
  {
    return frac;
  }
}

floatPower2

/* 
 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4
 */
unsigned floatPower2(int x)
{
  //返回无符号数
  //计算2.0的x次方
  //2.0^x = (1.0*2^1)^x = 1.0*2^x
  //exp = E + Bias = E + 127
  //x = E
  //frac = 1.0 -1 =0
  //在denorm中,令frac=000 0000 0000 0000 0000 0001时,M=2.0^22,E=-126
  //在denorm中,exp的位全为0,没有隐含的1
  int exp = x + 127;
  if (x > 127)
  {
    return (0xff << 23);
  }
  else if (x < -148)
  {
    return 0;
  }
  else if (x >= -126)
  {
    return (exp << 23);
  }
  else
  { //令frac中的一位为1
    int f = 148 + x;
    return (1 << f);
  }

语法检查均通过,若最后一个函数超时可以使用命令

./btest -T 20
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值