The Element Of Computer System 笔记(第二周)

第二周

二进制加法

两个二进制数能够从右至左一位一位相加,跟十进制加法一样。首先,把两个数的最右边的一位(也称为LSB,Least Significant Bits)加起来。然后,将两个位相加后的进位(0或者1)再与两个数的右起第二位相加。就按照这种方式计算下去,知道两个数最左边的一位(MSB,Most Significant Bits)为止。如果最后的两位数相加后产生了进位1,那么就说它产生了溢出;否则就说加法运算成功执行;
在这里插入图片描述
可以看到用于两个n-位数字二进制加法的计算机硬件可以由三位(两个计算位加上一个进位)加法的逻辑门构建而成。将进位转到下两个位上的加法是很容易实现的,只需要通过三位加法器门电路的正确引线即可实现。

有符号二进制数

n位二进制系统可以产生2的n次方个不同的组合。如果必须用二进制码表示有符号数,有个简单的方法就是,将这个空间分成两个相同的子集,一个子集用来表示正数,另一个表示负数。

如今几乎所有计算机都采用称为2-补码(2·s complement)的编码方式,也称为基补码(radix complement)。在n-位的二进制系统中,数x的2-补码定义如下:
在这里插入图片描述
举例来说,在一个5-位二进制系统中,-2的补码表示为2的五次方-00010=11110,也就是说只要00010+11110=00000即可。因为我们是在5-位二进制系统中,所以最左边的第6位被忽略掉了。通常,当补码表示法应用在n-位数字时,x+(-x)总是加到2的n次方(即1后面跟n个0)。下图显示了用补码表示的4-位二进制系统。
在这里插入图片描述

  • 系统能对所有2的n次方个有符号数进行编码,最大的数和最小的数分别为2的n-1次方-1和-2的n-1次方。
  • 所有正整数的编码的首位是0。
  • 所有负整数的编码的首位是1。
  • 为了通过x的编码获得-x的编码,所有最右边的0和左起的第一个1保持不变,然后将剩余的位取反。等价的捷径就是,对x的所有的位取反,然后再加上1,这个方案更容易在硬件中实现。

这种表示法有个特征:任何两个用补码表示的有符号数的加法和与整数的加法完全相同。例如-2+(-3),使用补码(用一个4-位表示),则要表示成1110+1101。我们不用关心这些代码表示的数字(正数还是负数),这个加法会得到结果1011(丢掉溢出位后)。结果正好是-5的补码表示法。

加法器

我们介绍三个加法器,并由此引出多位加法器芯片:

  • 半加器(Half-adder):用来进行两位加法。
  • 全加器(Full-adder):用来进行三位加法。
  • 加法器(Adder):用来进行两个n-位加法。
Half-adder(半加器)

半加器 进行二进制数加法的第一步就是要能够对两个二进制位进行相加。我们把结果的LSB位称为sum,MSB位称为carry。
在这里插入图片描述

/**
 * Computes the sum of two bits.
 */

CHIP HalfAdder {
    IN a, b;    // 1-bit inputs
    OUT sum,    // Right bit of a + b 
        carry;  // Left bit of a + b

    PARTS:
    // Put you code here:

    And(a=a,b=b,out=carry);
    Xor(a=a,b=b,out=sum);
}
Full-adder(全加器)

现在已经知道了如何对两个位进行相加,下图显示了全加器,用来对三个位相加。跟半加器一样,全加器电路也会产生两个输出:加法的LSB位和进位。
在这里插入图片描述

/**
 * Computes the sum of three bits.
 */

CHIP FullAdder {
    IN a, b, c;  // 1-bit inputs
    OUT sum,     // Right bit of a + b + c
        carry;   // Left bit of a + b + c

    PARTS:
    // Put you code here:
    HalfAdder(a=a,b=b,sum=s1,carry=c1);
    HalfAdder(a=c,b=s1,sum=sum,carry=c2);
    Or(a=c1,b=c2,out=carry);
}
Adder(加法器)

存储器和寄存器电路用n-位的形式来表示整数,n可以是16、32、64等等——这依赖于所在的计算机平台。进行n-位加法的芯片称为多位加法器(multi-bit adder),或者简称为加法器。下图展示了一个16-位加法器,对于任何n-位加法器,相同的逻辑和表示按比例增加。
在这里插入图片描述

/**
 * Adds two 16-bit values.
 * The most significant carry bit is ignored.
 */

CHIP Add16 {
    IN a[16], b[16];
    OUT out[16];

    PARTS:
   // Put you code here:
   HalfAdder(a=a[0],b=b[0],sum=out[0],carry=c1);
   FullAdder(a=a[1],b=b[1],c=c1,sum=out[1],carry=c2);
   FullAdder(a=a[2],b=b[2],c=c2,sum=out[2],carry=c3);
   FullAdder(a=a[3],b=b[3],c=c3,sum=out[3],carry=c4);
   FullAdder(a=a[4],b=b[4],c=c4,sum=out[4],carry=c5);
   FullAdder(a=a[5],b=b[5],c=c5,sum=out[5],carry=c6);
   FullAdder(a=a[6],b=b[6],c=c6,sum=out[6],carry=c7);
   FullAdder(a=a[7],b=b[7],c=c7,sum=out[7],carry=c8);
   FullAdder(a=a[8],b=b[8],c=c8,sum=out[8],carry=c9);
   FullAdder(a=a[9],b=b[9],c=c9,sum=out[9],carry=c10);
   FullAdder(a=a[10],b=b[10],c=c10,sum=out[10],carry=c11);
   FullAdder(a=a[11],b=b[11],c=c11,sum=out[11],carry=c12);
   FullAdder(a=a[12],b=b[12],c=c12,sum=out[12],carry=c13);
   FullAdder(a=a[13],b=b[13],c=c13,sum=out[13],carry=c14);
   FullAdder(a=a[14],b=b[14],c=c14,sum=out[14],carry=c15);
   FullAdder(a=a[15],b=b[15],c=c15,sum=out[15],carry=c16);
}
Inc16(增量器)

增量器 专门构建一个“对指定数字加1”的电路,这样做会带来很多便利。这里给出了一个16-位增量器的描述。
在这里插入图片描述

/**
 * 16-bit incrementer:
 * out = in + 1 (arithmetic addition)
 */

CHIP Inc16 {
    IN in[16];
    OUT out[16];

    PARTS:
   // Put you code here:
   Add16(a=in,b[0]=true,out=out);
}
ALU(算数逻辑单元)

Hack的ALU计算一组固定的函数out=f(x,y),这里x和y是芯片的两个16-位输入,out是芯片的16-位输出,f是位于一个函数表中的函数,该寒暑表由18个固定函数组成。我们通过设置六个称为控制位(control bits)的输入位来告诉ALU用哪一个函数来进行何种函数计算。下图给出了用伪代码表示的详细的输入/输出规范。

要注意的是,这六个控制位的每一位指示ALU来执行某个基本操作。这些操作的各种组合可以让ALU计算多种有用的函数。因为全部操作都是由六个控制位引起的,那么ALU可以对2的六次方=64个不同的函数进行操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
 * The ALU (Arithmetic Logic Unit).
 * Computes one of the following functions:
 * x+y, x-y, y-x, 0, 1, -1, x, y, -x, -y, !x, !y,
 * x+1, y+1, x-1, y-1, x&y, x|y on two 16-bit inputs, 
 * according to 6 input bits denoted zx,nx,zy,ny,f,no.
 * In addition, the ALU computes two 1-bit outputs:
 * if the ALU output == 0, zr is set to 1; otherwise zr is set to 0;
 * if the ALU output < 0, ng is set to 1; otherwise ng is set to 0. 
 */

// Implementation: the ALU logic manipulates the x and y inputs
// and operates on the resulting values, as follows:
// if (zx == 1) set x = 0        // 16-bit constant
// if (nx == 1) set x = !x       // bitwise not
// if (zy == 1) set y = 0        // 16-bit constant
// if (ny == 1) set y = !y       // bitwise not
// if (f == 1)  set out = x + y  // integer 2's complement addition
// if (f == 0)  set out = x & y  // bitwise and
// if (no == 1) set out = !out   // bitwise not
// if (out == 0) set zr = 1
// if (out < 0) set ng = 1

CHIP ALU {
    IN  
        x[16], y[16],  // 16-bit inputs        
        zx, // zero the x input?
        nx, // negate the x input?
        zy, // zero the y input?
        ny, // negate the y input?
        f,  // compute out = x + y (if 1) or x & y (if 0)
        no; // negate the out output?

    OUT 
        out[16], // 16-bit output
        zr, // 1 if (out == 0), 0 otherwise
        ng; // 1 if (out < 0),  0 otherwise

    PARTS:
   // Put you code here:
   Not16(in=x,out=notx);
   And16(a=x,b=notx,out=allzerox);
   Or16(a=x,b=notx,out=allonex);
   Mux4Way16(a=x,b=allzerox,c=notx,d=allonex,sel[0]=zx,sel[1]=nx,out=outx);

   Not16(in=y,out=noty);
   And16(a=y,b=noty,out=allzeroy);
   Or16(a=y,b=noty,out=alloney);
   Mux4Way16(a=y,b=allzeroy,c=noty,d=alloney,sel[0]=zy,sel[1]=ny,out=outy);

   And16(a=outx,b=outy,out=xandy);
   Add16(a=outx,b=outy,out=xaddy);
   Mux16(a=xandy,b=xaddy,sel=f,out=out1);

   Not16(in=out1,out=notout1);
   Mux16(a=out1,b=notout1,sel=no,out=out2);

   And16(a=out2,b[0..15]=true,out[0..7]=headout,out[8..15]=tailout);
   Or8Way(in=headout,out=headout1);
   Or8Way(in=tailout,out=tailout1);
   Not(in=headout1,out=notheadout1);
   Not(in=tailout1,out=nottailout1);
   And(a=notheadout1,b=nottailout1,out=zr);
   //Or(a=headout1,b=tailout1,out=outzr);
   //Not(in=outzr,out=zr);
   
   And16(a=out2,b[0..15]=true,out[0..14]=out14,out[15]=out15);
   And(a=out15,b=true,out=ng);
   And16(a=out2,b=true,out=out);
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值