计算机系统基础实验一

时间:2024-04-14 21:41:57

实验目的与要求

1.更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。

2. 加深对数据二进制编码表示的了解。

3. 使用有限类型和数量的运算操作实现一组给定功能的函数。

实验原理与内容

计算机实际上只能够进行逻辑计算——所有的计算类型最终都会转换为逻辑计算实现,无论多么复杂的功能性计算。所以,本实验的设计初衷为让学生进一步理解逻辑计算的各类应用,这有助于增强对于计算机硬件的理解(主要为CPU中的ALU的具体功能和计算实现过程)。为避免繁杂的仿真过程和HDL硬件描述语言的学习,使用标准C语言中的基本运算符和位操作来模拟硬件级别的逻辑计算过程。

实验要求学生们根据需要对bits.c中的相关函数进行编写(并修改掉return后面的返回值),实现各个小题所要求的函数功能。主要要求如下:

 

1 位操作题目列表

级别

函数名

功能

约束条件

最多操作符数

1

lsbZero

x的最低有效位(LSB)清零

仅能使用! ~ & ^ | + << >>

5

2

byteNot

x的第n个字节取反(字节从LSB开始到MSB依次编号为0-3

仅能使用! ~ & ^ | + << >>

6

2

byteXor

比较xy的第n个字节(字节从LSB开始到MSB依次编号为0-3),若不同,则返回1;若相同,则返回0

仅能使用! ~ & ^ | + << >>

20

3

logicalAnd

x&& y

仅能使用! ~ & ^ | + << >>

20

3

logicalOr

x|| y

仅能使用! ~ & ^ | + << >>

20

3

rotateLeft

x循环左移n

仅能使用! ~ & ^ | + << >>

25

4

parityCheck

x有奇数个1,则返回1;否则,返回0

仅能使用! ~ & ^ | + << >>

20

 

2 补码运算题目列表

级别

函数名

功能

约束条件

最多操作符数

2

mul2OK

计算2*x,如果不溢出,则返回1,否则,返回0

仅能使用~ & ^ | + << >>

20

2

mult3div2

计算(x*3)/2,朝零方向取整

仅能使用! ~ & ^ | + << >>

12

3

subOK

计算x –y,如果不溢出,则返回1,否则,返回0

仅能使用! ~ & ^ | + << >>

20

4

absVal

x的绝对值

仅能使用! ~ & ^ | + << >>

10

 

3 浮点数操作题目列表(此部分不做强制要求

级别

函数名

功能

约束条件

最多操作符数

2

float_abs

返回浮点数‘|f|’的二进制表示,当输入参数是NaN时,返回NaN

仅能使用任何整型/无符号整型操作,包括||&&以及ifwhile控制结构

10

4

float_f2i

返回浮点数‘f’的强制整型转换“(int)f”表示

仅能使用任何整型/无符号整型操作,包括||&&以及ifwhile控制结构

30

  根据以上说明,按照各小题的具体要求使用基本运算符和位操作完成bits.c中的函数,使其匹配要求所描述的功能,具体分为三大类:位操作、补码运算和浮点数操作。

 

实验过程中,如果需要对自己的编程结果/成绩进行确认,可以使用以下方法:

1. 按照要求使用规定范围内的操作符和常数实现各函数的功能。

2.函数编写完成并保存后,可以使用dlc检查函数实现代码是否符合实验要求的编码规则。具体使用方法如下:

a)   首先./dlc bits.c直接检测是否有不合规或编写错误。如图1.1所示:

 

 

 

由图知,输出Compilation Successful1 warning),故bits.c文件编写无强制性错误,符合要求。

b)   -e选项调用dlc,观察操作符数。得到提示后可通过对比题目要求来检查使用的操作符个数是否超限,如图1.2所示:

 

 

 

 

 

1.2

2.   使用 btest 检查函数实现代码的功能正确性并进行成绩计算。

a)   首先使用make编译生成btest可执行程序,如图1.3所示:

 

 

 

 

 

1.3

b)   然后调用 btest 命令检查 bits.c中所有函数的功能正确性。如图1.4所示:

 

 

 

 

1.4

由图知,35分中的35分被成功完成(此成绩将最后按照百分制进行核算按比例计入实验成绩)。注:最后两题不做强制性要求,所以不必在乎是否得分为满分35分。

实验过程与结果(可贴图)

/*

 *   lsbZero - set 0 to the least significant bit of x

 *   Example: lsbZero(0x87654321) = 0x87654320

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 5

 *   Rating: 1

 */

X右移一位再左移一位实现把最低有效位置

int lsbZero(int x) {

    x = x>>1;

    x = x<<1; 

    return x;

}

/*

 * byteNot - bit-inversion to byte n from word x 

 *   Bytes numbered from 0 (LSB) to 3 (MSB)

 *   Examples: getByteNot(0x12345678,1) = 0x1234A978

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 6

 *   Rating: 2

 */

Xn个字节每位都和1异或实现取反

int byteNot(int x, int n) {

    int y = 0xff;

    n = n<<3;

    y = y<<n;

    x = (x^y);

    return x;

}

/*

 *   byteXor - compare the nth byte of x and y, if it is same, return 0, if not, return 1

 

 *   example: byteXor(0x12345678, 0x87654321, 1) = 1

 

 *            byteXor(0x12345678, 0x87344321, 2) = 0

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 2

 */

xy的第n个字节取出来异或,再转换为逻辑的01

int byteXor(int x, int y, int n) {

    n = n<<3;

    x = x>>n;

    y = y>>n;

    x = x&(0xff);

    y = y&(0xff);

    return !!(x^y);

}

/*

 *   logicalAnd - x && y

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 3

 */

xy分别转换为逻辑的01,再相与

int logicalAnd(int x, int y) {

    x = (!(!x))&(!(!y)); 

    return x;

}

/*

 *   logicalOr - x || y

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 3

 */

int logicalOr(int x, int y) {

    x = (!(!x))|(!(!y)); 

    return x;

}

xy分别转换为逻辑的01,再相或

/*

 * rotateLeft - Rotate x to the left by n

 *   Can assume that 0 <= n <= 31

 *   Examples: rotateLeft(0x87654321,4) = 0x76543218

 *   Legal ops: ~ & ^ | + << >> !

 *   Max ops: 25

 *   Rating: 3

 */

先构造低n位为1,高(n-32)位为零的数zx再左移n位后的数加上x右移(32-n)位的数&z即可

int rotateLeft(int x, int n) {

    int z;

    z = ~(((1<<31)>>31)<<n);

    x = ((x>>(32+(~n+1)))&z)+(x<<n); 

    return x;

}

/*

 * parityCheck - returns 1 if x contains an odd number of 1\'s

 *   Examples: parityCheck(5) = 0, parityCheck(7) = 1

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 4

 */

每次将数的低半数位与高半数位比较,再把y右移31位,最后把y转化为逻辑的01

int parityCheck(int x) {

    int y;

    y = x<<16;

    y = y^x;

    y = y^(y<<8);

    y = y^(y<<4);

    y = y^(y<<2);

    y = y^(y<<1);

    y = y>>31;

    return !(!y);

}

/*

 * mul2OK - Determine if can compute 2*x without overflow

 *   Examples: mul2OK(0x30000000) = 1

 *             mul2OK(0x40000000) = 0

 *        

 *   Legal ops: ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 2

 */

x30位和30位分别和1做按位与,再异或,再和1异或

int mul2OK(int x) {

    int m;

    m = ((x>>30)&0x1)^((x>>30)&0x1);

    return m^0x1;

}

/*

 * mult3div2 - multiplies by 3/2 rounding toward 0,

 *   Should exactly duplicate effect of C expression (x*3/2),

 *   including overflow behavior.

 *   Examples: mult3div2(11) = 16

 *             mult3div2(-9) = -13

 *             mult3div2(1073741824) = -536870912(overflow)

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 12

 *   Rating: 2

 */

左移一位再+xx*3,右移一位的时候,当y的最高位和最低为都为0时还要加1

int mult3div2(int x) {

    int y = (x<<1)+x;

    y = (y>>1)+(((y>>31)&1)&(((y<<31)>>31)&1));

    return y;

}

/*

 * subOK - Determine if can compute x-y without overflow

 *   Example: subOK(0x80000000,0x80000000) = 1,

 *            subOK(0x80000000,0x70000000) = 0,

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 20

 *   Rating: 3

 */

x的最高有效位和y的最高有效位不同且x和(x-y)的最高位不同才能判断溢出

int subOK(int x, int y) {

    int m = (x>>31)&1;

    int n = (y>>31)&1;

    x = (m^n)&(m^(((x+(~y+1))>>31)&1));

    return (!x);

}

/*

 * absVal - absolute value of x

 *   Example: absVal(-1) = 1.

 *   You may assume -TMax <= x <= TMax

 *   Legal ops: ! ~ & ^ | + << >>

 *   Max ops: 10

 *   Rating: 4

 */

X的最高位为0时就是x,最高位为1时是~x+1

int absVal(int x) {

    int  y = x>>31;

    x = (y&(~x+1))+((~y)&x);

    return x;

}

/*

 * float_abs - Return bit-level equivalent of absolute value of 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 representations of

 *   single-precision floating point values.

 *   When argument is NaN, return argument..

 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while

 *   Max ops: 10

 *   Rating: 2

 */

unsigned float_abs(unsigned uf) {

    return 2;

}

/*

 * float_f2i - 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 float_f2i(unsigned uf) {

    return 2;

}

实验结果截图:

 

 

 

操作异常问题与解决方案

异常:对于按位与、或、异或、加的运算的规则不是很了解

解决:百度+****

实验总结

经过本次实验让我更好地熟悉和掌握计算机中整数的二进制编码表示。加深对数据二进制编码表示的了解。使用有限类型和数量的运算操作实现一组给定功能的函数。让我了解到左移运算将一个位串信息向左移指定的位,右端空出的位用0补充,每左移1位相当于乘2;右移运算将一个位串信息向右移指定的位,右端移出的位的信息被丢弃,每右移1位,相当于除以2。对无符号数据,右移时,左端空出的位用0补充。对于带符号的数据,如果移位前符号位为0(正数),则左端也是用0补充;如果移位前符号位为1(负数),则左端用0或用1补充,取决于计算机系统。对于负数右移,称用0补充的系统为逻辑右移,用1补充的系统为算术右移。按位取反为二进制串对应的10进行变换逻辑取反只有0和非0两种情况

 

 

 

 

实验原理与内容

计算机实际上只能够进行逻辑计算——所有的计算类型最终都会转换为逻辑计算实现,无论多么复杂的功能性计算。所以,本实验的设计初衷为让学生进一步理解逻辑计算的各类应用,这有助于增强对于计算机硬件的理解(主要为CPU中的ALU的具体功能和计算实现过程)。为避免繁杂的仿真过程和HDL硬件描述语言的学习,使用标准C语言中的基本运算符和位操作来模拟硬件级别的逻辑计算过程。

实验要求学生们根据需要对bits.c中的相关函数进行编写(并修改掉return后面的返回值),实现各个小题所要求的函数功能。主要要求如下:

 

1 位操作题目列表

级别

函数名

功能

约束条件

最多操作符数

1

lsbZero

x的最低有效位(LSB)清零

仅能使用! ~ & ^ | + << >>

5

2

byteNot

x的第n个字节取反(字节从LSB开始到MSB依次编号为0-3

仅能使用! ~ & ^ | + << >>

6

2

byteXor

比较xy的第n个字节(字节从LSB开始到MSB依次编号为0-3),若不同,则返回1;若相同,则返回0

仅能使用! ~ & ^ | + << >>

20

3

logicalAnd

x&& y

仅能使用! ~ & ^ | + << >>

20

3

logicalOr

x|| y

仅能使用! ~ & ^ | + << >>

20

3

rotateLeft

x循环左移n

仅能使用! ~ & ^ | + << >>

25

4

parityCheck

x有奇数个1,则返回1;否则,返回0

仅能使用! ~ & ^ | + << >>

20

 

2 补码运算题目列表

级别

函数名

功能

约束条件

最多操作符数

2

mul2OK

计算2*x,如果不溢出,则返回1,否则,返回0

仅能使用~ & ^ | + << >>

20

2

mult3div2

计算(x*3)/2,朝零方向取整

仅能使用! ~ & ^ | + << >>

12

3

subOK

计算x –y,如果不溢出,则返回1,否则,返回0

仅能使用! ~ & ^ | + << >>

20

4

absVal

x的绝对值

仅能使用! ~ & ^ | + << >>

10

 

3 浮点数操作题目列表(此部分不做强制要求

级别

函数名

功能

约束条件

最多操作符数

2

float_abs

返回浮点数‘|f|’的二进制表示,当输入参数是NaN时,返回NaN

仅能使用任何整型/无符号整型操作,包括||&&以及ifwhile控制结构

10

4

float_f2i

返回浮点数‘f’的强制整型转换“(int)f”表示

仅能使用任何整型/无符号整型操作,包括||&&以及ifwhile控制结构

30

  根据以上说明,按照各小题的具体要求使用基本运算符和位操作完成bits.c中的函数,使其匹配要求所描述的功能,具体分为三大类:位操作、补码运算和浮点数操作。

 

实验过程中,如果需要对自己的编程结果/成绩进行确认,可以使用以下方法:

1. 按照要求使用规定范围内的操作符和常数实现各函数的功能。

2.函数编写完成并保存后,可以使用dlc检查函数实现代码是否符合实验要求的编码规则。具体使用方法如下:

a)   首先./dlc bits.c直接检测是否有不合规或编写错误。如图1.1所示:

 

1.1

由图知,输出Compilation Successful1 warning),故bits.c文件编写无强制性错误,符合要求。

b)   -e选项调用dlc,观察操作符数。得到提示后可通过对比题目要求来检查使用的操作符个数是否超限,如图1.2所示:

 

1.2

2.   使用 btest 检查函数实现代码的功能正确性并进行成绩计算。

a)   首先使用make编译生成btest可执行程序,如图1.3所示:

 

1.3

b)   然后调用 btest 命令检查 bits.c中所有函数的功能正确性。如图1.4所示:

 

1.4

由图知,35分中的35分被成功完成(此成绩将最后按照百分制进行核算按比例计入实验成绩)。注:最后两题不做强制性要求,所以不必在乎是否得分为满分35分。