[CSAPP-Data Lab]

这篇博客介绍了一个C语言实验,学生需要在高度受限的环境中实现逻辑、补码和浮点数运算,如求绝对值、位异或、最小两补数整数检测等。实验要求使用位操作如按位与、按位或、按位异或、左移和右移,禁止使用控制结构、宏定义和额外函数。对于浮点数运算,规则稍微放宽,允许使用循环和条件控制。实验还包括了用位操作计算2的幂以及检查是否为最大两补数数等挑战性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Students implement simple logical, two's complement, and floating point functions, but using a highly restricted subset of C. For example, they might be asked to compute the absolute value of a number using only bit-level operations and straightline code. This lab helps students underst-and the bit-level representations of C data types and the bit-level behavior of the operations on data.

Chief code

/* 
 * 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 <= x <= 31
   */
  int pow2plus4(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     int result = (1 << x);
     result += 4;
     return result;
  }

FLOATING POINT CODING RULES

For the problems that require you to implement floating-point operations,
the coding rules are less strict.  You are allowed to use looping and
conditional control.  You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants. You can use any arithmetic,
logical, or comparison operations on int or unsigned data.

You are expressly forbidden to:
  1. Define or use any macros.
  2. Define any additional functions in this file.
  3. Call any functions.
  4. Use any form of casting.
  5. Use any data type other than int or unsigned.  This means that you
     cannot use arrays, structs, or unions.
  6. Use any floating point data types, operations, or constants.


NOTES:
  1. Use the dlc (data lab checker) compiler (described in the handout) to 
     check the legality of your solutions.
  2. Each function has a maximum number of operations (integer, logical,
     or comparison) that you are allowed to use for your implementation
     of the function.  The max operator count is checked by dlc.
     Note that assignment ('=') is not counted; you may use as many of
     these as you want without penalty.
  3. Use the btest test harness to check your functions for correctness.
  4. Use the BDD checker to formally verify your functions
  5. The maximum number of ops for each function is given in the
     header comment for each function. If there are any inconsistencies 
     between the maximum ops in the writeup and in this file, consider
     this file the authoritative source.

/*
 * STEP 2: Modify the following functions according the coding rules.
 * 
 *   IMPORTANT. TO AVOID GRADING SURPRISES:
 *   1. Use the dlc compiler to check that your solutions conform
 *      to the coding rules.
 *   2. Use the BDD checker to formally verify that your solutions produce 
 *      the correct answers.
 */


#endif
//1
/* 
 * 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 - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {

  return (1<<31);

}
//2
/*
 * 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) {
  return !(((1<<31)^(-1))^x);
}
/* 
 * 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 tmp=0xAA+(0xAA<<8);
  tmp=tmp+(tmp<<16);
  return !((x&tmp)^tmp);
}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return (~x)+1;
}
//3
/* 
 * 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 tmp1=(~0x30)+1;
  int tmp2=(~0x3A)+1;
  return (!(((x+tmp1)>>31)&1))&(((x+tmp2)>>31)&1);
}

/* 
 * 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) {
  int n1=(~1)+1;
  int op=(!x)+n1;
  return (op&y)+(~op&z);
}
/* 
 * 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 sx=(x>>31)&1;
  int sy=(y>>31)&1;
  return ((!(sx^sy))&(!(((y+(~x)+1)>>31)&1)))|((sx^sy)&sx);
}
//4
/* 
 * 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) {
  return (((((~x)+1)>>31)&1)|((x>>31)&1))^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 op=x>>31;
  x=(op&~x)+(~op&x);
  int op5=!!(x>>16)<<4; x=x>>op5;
  int op4=!!(x>>8)<<3;  x=x>>op4;
  int op3=!!(x>>4)<<2;  x=x>>op3;
  int op2=!!(x>>2)<<1;  x=x>>op2;
  int op1=!!(x>>1);     x=x>>op1;
  int op0=x;
  return op0+op1+op2+op3+op4+op5+1;
}
//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) {
  unsigned exp=(uf>>23)&(0xff);
  unsigned sign=uf&(1<<31);
  if(exp==0xff)return uf;
  if(exp==0) return (uf<<1)|sign;
  exp=exp+1;
  return (uf&(0x807fffff))|(exp<<23);
}
/* 
 * 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 exp=(uf>>23)&(0xff);
  unsigned sign=(uf>>31)&1;
  int E=exp-0x7f;
  if(exp==0){
  	if(E>32)return 0x80000000u;
  	if(E<=0)return 0;
  	int val=(0x007fffff&uf);
  	if(E>=23){
      if(sign) return (~(val<<(E-23)))+1;
      else return val<<(E-23);
    }
  	else{
      if(sign) return (~(val>>(23-E)))+1;
      else return val>>(23-E);
    } 
  }else{
  	if(E>31)return 0x80000000u;
  	if(E<0)return 0;
  	int val=(0x007fffff&uf)|(1<<23);
  	if(E>=23){
      if(sign) return (~(val<<(E-23)))+1;
      else return val<<(E-23);
    }
  	else{
      if(sign) return (~(val>>(23-E)))+1;
      else return val>>(23-E);
    } 
  }
  return 0;
}
/* 
 * 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) {
  if(x==-127||x<-150)return 0;
  if(x>127)return 0xff<<23;
  if(-150<=x&&x<=-128){
    int tmp=-127-x;
    return 1<<(23-tmp);
  }
  if(-126<=x&&x<=127){
    return ((x+127)<<23);
  }
  return 0;
}

Results

### CSAPP DataLab 武汉大学 `subok` 参数教程 #### 关于 CSAPP DataLab 的背景介绍 CSAPP DataLab 是《计算机系统基础》(Computer Systems: A Programmer's Perspective, CSAPP)教材中的一个重要实验部分,旨在通过一系列基于位运算的操作加深学生对底层硬件和数据表示的理解[^1]。 在完成 DataLab 中的任务后,通常需要将解决方案上传到特定的服务器进行验证。这一过程涉及到了一个名为 `subok` 的参数设置问题。以下是关于如何正确配置以及提交的相关说明: #### 配置与使用 `subok` 参数 当准备向官方或者学校指定平台提交代码时,确保命令行工具能够识别并接受额外选项是非常重要的一步。具体来说,在执行如下形式的提交指令前需确认环境变量已正确定义好: ```bash make submit SUBMITTY_URL="http://your-submission-server/" COURSE_ID="csapp-datalab" USER_ID="wuhan-university-student" ``` 其中涉及到的关键点之一就是——是否允许未优化版本也成功递交?这便是由布尔型标志 `subok` 来决定的事情。如果将其设为 true,则即使某些题目未能达到最优解法的要求也能顺利完成整个流程;反之则会阻止不符合标准的结果被接收[^2]。 因此,在实际操作过程中需要注意以下几点事项来保障顺利通过检验环节: - **检查本地测试结果**:利用自带脚本如 `./btest` 对各个实现逐一校验其功能性和效率指标; ```bash make && ./btest -f functionName [-param value ...] ``` - **调整适当编译器警告级别**:有时候看似无害的小错误可能隐藏着逻辑隐患,故建议启用更严格的检测机制以便及时发现潜在缺陷; - **明确了解评分细则**:不同院校可能会依据实际情况定制化评判准则,务必提前查阅清楚后再着手修改源文件内容直至满足预期目标为止[^3]。 最后附上一段简单示例展示如何构造符合规范要求下的基本框架结构供参考学习之用: ```c /* * Example Function Implementation According To Given Constraints. */ int exampleFunction(int input){ int mask = 0xFFFFFFFF; return ((input >> 1) & mask); } ``` #### 注意事项总结 综上所述,为了保证能够在武汉大学或者其他任何采用相同体系架构的教学场景下高效完成相应练习项目,请牢记上述提到的各项要点,并严格按照指导手册上的提示逐步推进各项工作进程即可达成理想效果[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值