Lab 1 Data Lab
写在前言:这个实验的来源是CSAPP官网:CSAPP Labs ,如果感兴趣的话,可以点击这个链接🔗去下载,Data Lab这个实验可以检验我们对数据的编码以及IEEE754浮点数格式的掌握程度,只有我们充分掌握了CSAPP书上第二章的内容,对于这个实验,可以说是游刃有余了,Data Lab包含整数和浮点数编码两部分,相应的会做出一些限制,主要任务就是让我们用位级操作实现一些功能。
编码限制
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.
bitXor
函数的声明和限制如下:
//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 0;
}
这道题目限制使用两个操作符:按位取反~、按位与&,根据离散数学的基本等值式:异或可以表示为:
因此答案是:
int bitXor(int x, int y) {
int result = ~(~(~x & y) & ~(x & ~y));
return result;
}
tmin
函数声明如下:
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 0;
}
要求我们得到32位补码整数的最小值,就是0x80000000
,可以使用一个简单的移位实现
答案为:
int tmin(void) {
int result = 1 << 31;
return result;
}
isTmax
函数声明如下:
//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 0;
}
要求我们判断 x 是否为32位补码整数最大值0x7fffffff
,一种思路是先生成Tmax32
,然后在使用异或 ^ 和逻辑非 ! 操作符判断 x 是否是 Tmax32
,
int isTmax(int x) {
int tmax = (1 << 31) - 1;
return !(x ^ tmax);
}
如果 x=Tmax
,那么表达式 !(x ^ tmax)=1
,因为 a^a=0
,两个相同的数进行异或一定为0。
但是题目要求这里不能使用减法和移位操作,所以要另辟蹊径。
对于 Tmax
,有一个性质:(Tmax+1) + (Tmax+1)=(0x7fffffff+1)+(0x7fffffff+1)=0x80000000+0x80000000=0
,意味着我们可以考虑计算表达式 (x+1)+(x+1)
判断它是否为0就可以了,但是这个性质对于x=-1
也是满足的,所以还需要排除这个情况:
int isTmax(int x) {
int expr = (x + 1) + (x + 1);
// x is Tmax if expr = 0 and x != -1
int istmax = !expr & !!(x + 1);
return istmax;
}
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) {
return 0;
}
要求我们判断x的奇数位是否全部设置为了1,因为只需要考虑奇数位,可以先生成一个奇数位掩码0xAAAAAAAA
,位级整数编码要求我们只能使用0-0xff
这种小整数,所以不能直接使用这种大整数,可以通过0xAA
移位合并起来,然后生成掩码后,按位与 x,将结果和这个掩码判断,如果相等,那么所有奇数位为1:
int allOddBits(int x) {
int mask = (0xAA << 24) | (0xAA << 16) | (0xAA << 8) | 0xAA;
int result = !((mask & x) ^ mask);
return result;
}
negate
函数声明如下:
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return 0;
}
要求计算表达式 -x,但不使用减号,很简单,根据位级整数的性质:-x=~x+1
,
int negate(int x) {
int result = ~x + 1;
return result;
}
isAsciiDigit
函数声明如下:
//3
/*
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
* Example: isAsciiDigit(0x35) = 1.
*