DATA LAB
目录
注意事项
1.环境配置
在终端命令窗口输入以下三行指令。
> sudo apt-get install build-essential
> sudo apt-get install gcc-multilib
> sudo apt-get install gdb
2.实验说明
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 understand the bit-level representations of C data types and the bit-level behavior of the operations on data.
3.实验目的
修改bits.c的副本,使其通过btest中的所有测试,而不违反任何编码准则。
4. 实验文件
makefile -生成btest、fshow和show
readme -说明文件
bits.c -你将修改并提交的文件(函数实现的文件)
bits.h -头文件
btest.c -主要的btest程序
btest.h -用于构建btest
decl.c -用于构建btest
tests.c - 用于构建btest
test-header.c - 用于构建btest
dlc* -规则检查编译器二进制(数据实验室编译器)
driver .pl* -使用btest和dlc自动升级位的驱动程序
Driverhdrs.pm -可选的“击败教授”比赛的头文件
fshow.c -用于检查浮点表示的工具
ishow.c -用于检查整数表示的实用程序
附:
- 按位右移>> :
对有符号数都是算数右移(最高位是0补0,最高位是1补1)
对无符号数都是逻辑右移(最高位补0) - 提取符号的方法:x&1 (格式化该数,得到其符号)
函数实现
1. bitXOR
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/用~和&计算x^y
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
*/
int tmin(void) {
return 0x1 << 31;
// the minimum = 1000...0
}
int 占4字节32位,求最小值则是得到(0x8000,0000),将0x1左移,右边补零则可以得到。
3. isTmax
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/如果是最大值(0x7fffffff)则返回1,否则都返回0。
int isTmax(int x) {
// the max 0111...111
int i = x + 1; // or int i = ~x
x = x + i;
x = ~x; // x = 0
// if x = max ; i = 10..0; !i = 0
// if x = oxff..ff; i = 0x0 ; !i = 1
i = !i;
x = x + i;
return !x;
}
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 ,从第0位一直到第31位。
int allOddBits(int x) {
// oxAA..AA
int a = 0xAA;
int i = a + (a << 8);
i = i + (i << 16);
// a^a = 0
// x&i = prevents even bits fron being 1
return !((x&i) ^ i);
}
首先构造i=0xAAAAAAAA,然后通过&保留下x的奇数位,再与i异或,如果完全一致则值应为0,最后!(0)得到1。
5. negate
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
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~0x39之间,如果在,返回1,否则返回1.
int isAsciiDigit(int x) {
// -x = ~x +1
// 0x30 =< x =< 0x39
// x - 0x30>= 0; 0x39 - x>= 0
int a = x + (~(0x30) + 1);
int b = 0x39 + (~(x)+1);
int c = a >> 31; // >=0 c=0, <0 c=-1
int d = b >> 31;
return (!c)&(!d);
}
7.conditional
/*
* conditional - same as x ? y : z
* Example: conditional(2,4,5) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 16
* Rating: 3
*/实现三目运算符,如果x不为0,输出y;否则输出z
int conditional(int x, int y, int z) {
x = !!x;
x = ~x + 1;
return (x&y) | (~x&z);
}
只有在x=0x0时,!(x) = 1 ,!!(x)=0。
但是我提交了却出现错误,不是很懂,逻辑上应该没有问题得。
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;
int isLessOrEqual(int x, int y) {
int negX = ~x + 1; //-x
int a = y + negX; //y-x
int yx = a >> 31 & 1; //y-x的符号
int x1 = x >> 31 & 1; //x的符号
int y1 = y >> 31 & 1; //y的符号
int Sign = x1 ^ y1; //判断x,y的符号是否相同,如果相同,返回0,否则返回1
return (!Sign & !yx) | (Sign&x1);
}
这题要注意得不能之间按上面是否存在0x30与0x39之间得解法计算,因为两者之间得数存在上下界,而这里只有一边有边界,可能发生溢出。
将这里得x小于等于y分成两种情况:
1.) 两者符号相同,并且y-x>=0的符号为正
2.)两者的符号不同,并且x的符号为负,这样y一定大于x
最后用 | 输出结果。
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,否则返回1。就是实现!的功能
int logicalNeg(int x) {
int y = (x | (~x + 1)) >> 31;
// x!=0 y=-1; x=0,y=0
return y+1;
}
只有当x=0时,(x|(~x+1))的符号为0,其余均为1。然后经过算术右移,y=0或者-1。
当x=0 -> y = 0 -> return y+1(1)
当x!=0 -> y = -1 -> return y+1(0)
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
*/(12) = 01100 ; (298) = 256+32+8+2 = 0100001010
求表示的最小位数,不过不是很懂这个-1用一位表示。
int howManyBits(int x) {
int b16, b8, b4, b2, b1, b0;
int sign = x >> 31;
x = (sign&~x) | (~sign&x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)
// 不断缩小范围
b16 = !!(x >> 16) << 4;//高十六位是否有1
x = x >> b16;//如果有(至少需要16位),则将原数右移16位
b8 = !!(x >> 8) << 3;//剩余位高8位是否有1
x = x >> b8;//如果有(至少需要16+8=24位),则右移8位
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表示加上符号位
}
首先要将判断符号,如果是负数,要按位取反。因为对于正数来说,最小位数是寻找从左往右的第一个1,在前面加上一个符号位0,就是最小位数。而负数如-5,补码的表示可以为10011也可以为110011或者1110011,所以对于负数,最小位数是找到从左往右的第一个0,然后加上一个符号位。为了和正数统一寻找方式,将负数按位取反,这样就和正数一样,最小位数是寻找从左往右的第一个1,在前面加上一个符号位0。
用一个最大值(0x7fffffff)来解释最少需要多少位数的过程。
之后再补充浮点数的实验。