CSAPP 3.0-Data Lab

CSAPP Lab官网
CUM Intro to Computer Systems课程官网
本文是对CSAPP3.0实验一Data Lab的实验记录,主要参考了这篇文章:https://zhuanlan.zhihu.com/p/59534845?utm_source=qq

题目列表

在这里插入图片描述

题解

bitXor

“异或”是两数不同则为1,相同则为0。故返回1时,两数不能同时为0,也不能同时为1:~(~x&~y)&~(x&y),也可以表达为x=0,y=1或y=0,x=1:(~x&y)|(~y&x)。本题不能使用|符号,故选择第一种。

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

返回INT_MIN。

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  return (1 << 31);
}
isTmax

判断整数类型是否等于INT_MAX。当x=0xffffffff时,i=x+1=0x+i==0xffffffff,与x==INT_MAX时情况一样,应该排除。

/*
 * 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) {
  int i = x + 1;  // INT_MAX + 1 = INT_MIN, 0x80000000
  x += i; // -1, 0111... + 1000... = 1111...
  x = ~x; // 0
  i = !i; // exclude x == 0xffff...
  x += i; // exclude x == 0xffff...
  return !x;
}
allOddBits

如果所有的奇数位为1,就返回1;否则,返回0。注意这道题不能使用超过255的整型常量。

/* 
 * 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) {
  int mask = 0xAA + (0xAA << 8);
  mask = mask + (mask << 16);
  return !((mask & x) ^ mask);
}
negate

返回整数的负数。

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

如果x是字符'0'~'9'之间的数就返回1,否则返回0。

/* 
 * 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) {
  int sign = 1 << 31;
  int upperBound = ~(sign | 0x39);
  int lowerBound = ~0x30 + 1; // -0x30
  upperBound = sign & (upperBound + x); // 如果x>0x39,则upperBound + x会向符号位进位,则符号位为1
  lowerBound = sign & (lowerBound + x); // 如果x<0x30,则lowerBound + x == x - 0x30 < 0,得到负数,符号位为1
  return !(upperBound | lowerBound); // 只要存在x>0x39或x<0x30,则返回0
}
conditional

实现条件语句,如x ? y : z

/* 
 * 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值设为0或1
  x = ~x + 1;	// x的位级为全0或全1
  return (x & y) | (~x & z);
}
isLessOrEqual

判断x<=y是否成立。如果x,y同号,则y-x>=0时成立;否则x,y异号,正数较大,故x为负数时成立。

/* 
 * 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 negX = ~x + 1;    // -x
  int addX = negX + y;  // y - x
  int checkSign = (addX >> 31) & 1; // y-x的符号位 neg:1, pos:0
  int xSign = (x >> 31) & 1;  // sign of x
  int ySign = (y >> 31) & 1;
  int bitXor = xSign ^ ySign; // x,y是否同号,同号为0,异号为1
  return ((!bitXor) & (!checkSign)) | (bitXor & xSign);
}
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外的任何数(包括TMin),和它的负数取或,符号位均为1
  // 故算数右移之后为0xffffffff
  return ((x | (~x + 1)) >> 31) + 1;
}
howManyBits

补码表达x需要多少位。需要1位记录符号位,当x>=0时,找到最高的1位;当x<0时,找到最高的0位,将该位记为第n位,n+1即为所求结果。

/* 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) {
  int b16, b8, b4, b2, b1, b0;
  int sign = x >> 31; // 如果是负,则右移之后32位全为1
  x = (sign & ~x) | (~sign & x);  // 如果x为负,则按位取反,找最高的0位改为找最高的1位即可
// 二分法找到最高位的1
  b16 = !!(x >> 16) << 4; // 高16位里是否有1
  x = x >> b16;           // 如果有,右移16位
  b8 = !!(x >> 8) << 3;   // ! 优先级大于 <<
  x = x >> b8;
  b4 = !!(x >> 4) << 2;
  x = x >> b4;
  b2 = !!(x >> 2) << 1;
  x = x >> b2;
  b1 = !!(x >> 1);
  x = x >> b1;
  b0 = x;
  return b16 + b8 + b4 + b2 + b1 + b0 + 1; // +1是符号位
}
floatScale2

返回2*f的位级表示。

/* 
 * 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) {
  unsigned sign = uf >> 31;
  unsigned exp = uf >> 23 & 0xff;
  if(exp == 0) return (uf << 1) | sign << 31;
  if(exp == 255)        // NaN and oo
    return uf;
  exp++;
  if(exp == 255) return 0x7f800000 | sign << 31; // +-oo
  return (exp << 23) | (uf & 0x807fffff);
}
floatFloat2Int

将浮点型转化为整型。此题和课本中家庭作业第2.96题一样。注意将sign,exp,frac都设为int而不是unsigned

/* 
 * 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) {
  int sign = uf >> 31;
  int exp = (uf >> 23 & 0xff) - 127;      // E = e - bias
  int frac = (uf & 0x007fffff) | 0x00800000; // M = 1 + f,因为在整数范围内的都是规格化数
  // 正负零都是零
  if(!(uf & 0x7fffffff)) return 0;
  // 超出整数范围
  if(exp > 31) return 0x80000000u;
  if(exp < 0) return 0;
  // 移动frac,即 V = 2^E * M
  if(exp > 23) frac <<= (exp - 23);
  else frac >>= (23 - exp);
  // 判断符号
  if(!((frac >> 31) ^ sign)) return frac;
  else if(frac >> 31) return 0x80000000u; // 溢出
  else return ~frac + 1; // -frac
}
floatPower2

返回2^x的位级表示。此题和家庭作业第2.90题一样。

/* 
 * 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){
  unsigned exp, frac;
  if(x < -149){
    // Too small. Return 0.0
    exp = 0;
    frac = 0;
  }else if(x < -126){
    // Denormalized result
    exp = 0;
    frac = 1 << (x + 149);
  }else if(x < 128){
    // Normalized result
    exp = x + 127;
    frac = 0;
  }else{
    // Too big. Return +oo
    exp = 255;
    frac = 0;
  }
  return exp << 23 | frac;
}

进行测试时发现最后一题会超时。
在这里插入图片描述
解决方法是将btest.c文件中TIMEOUT_LIMIT由10改为了15(限制时间增加一点就没问题了。。因为实在找不到其他解决方案了。。看了一些网友的题解和我的思路差不多。。还是会超时。。)
在这里插入图片描述
使用./driver.pl命令可以查看使用的操作符个数。
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刷子c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值