TBH我很难理解逻辑门图,因为我还没有完全理解底层电子设备及其所有工作原理。
我有一些有关基本逻辑门的学习经验,在观看了几段视频并进行了很多思考之后,我可以在几分钟内了解它。
但是后来我看到了一些在软件中“实现”的“逻辑门”的例子,这使发生的事情更加有意义。例如,here。
然后,我什至可以更深入地了解full adder的工作方式,如here:
function fullAdder(a,b,c){
return {
c:or(and(xor(a,b),c), and(a,b)), // C is the carry
s:xor(xor(a,b),c) // S is the sum
};
}
与逻辑图相比,这是非常基本的。
现在,我想了解multiplication和division是如何在逻辑门中实现的,例如x86的MUL运算符。
function MUL(a,b){
return {
...
};
}
除了花一些严肃的时间来理解乘法器电路,然后尝试使用上述示例将其转化为也许与非门的实现之外,我真的不知道从哪里开始。想知道是否已经知道这一点的人可以演示JavaScript的实现。
答案 0 :(得分:1)
乘法依赖于数字以二进制编码的方式。
如果A为无符号并由a_n-1,a_n-2,...,a_1,a_0位编码,则其值为
A = a_n-1 * 2 ^ n-1 + a_n-2 * 2 ^ n-2 + ... + a_1 * 2 ^ 1 + a_0
所以要乘以A×B,必须做
A×B = A×(b_n-1 * 2 ^ n-1 + b_n-2 * 2 ^ n-2 + ... + b_1 * 2 ^ 1 + b_0)
= A×b_n-1 * 2 ^ n-1 + A×b_n-2 * 2 ^ n-2 + ... + A×b_1 * 2 ^ 1 + A×b_0
乘法只是一个很大的加法,其中每一项A×b_i * 2 ^ i如果b_i == 1则为A×2 ^ i,如果b_i == 0则为0
这是C语言的实现
int mult(unsigned short A, unsigned short B){
int res=0;
int mask=0x1;
for(int i=0; i<16;i++,mask<<=1){
if(B&mask)
res += (A << i);
}
return res;
}
b_i上的测试可以用“与”门代替。
int mult(unsigned short A, unsigned short B){
int res=0;
int mask=0x1;
for(int i=0; i<16;i++,mask<<=1){
res += (A&~(((B&mask)>>i) -1))<<i;
}
return res;
}
这个奇特的表达式提取B(B&mask
)的第i位,将其放在LSB(>>i
)处,减去1,这样我们得到1-1 = 0,它的位是1, -1 = 0xffffffff否则。我们只需要对A进行补码并进行“与”运算就可以得到A或0(取决于第i位)。幸运的是,硬件方面的工作更加轻松。复制B的b_i位并对A的每一位做一个“与”就足够了。
为简化硬件,A<<i
的可变移位可以在每一步(A=A<<1
)处用A的左移1位代替。对于b_i提取,可以进行类似的修改,使得我们始终考虑B的LSB。
int mult(unsigned short A, unsigned short B){
int res=0;
int mask=0x1;
for(int i=0; i<16;i++){
res += A&~((B&mask) -1);
A <<= 1;
B >>= 1;
}
return res;
}
展开循环后,这或多或少是简单乘法器在硬件中的外观。 您可以在js中实现它,并用由Gates完成的加法器替换+,并使用模拟的“ and”门。
实际上,硬件乘法器要复杂一些。
它们使用不带进位传播的特殊加法器来减少加法时间(进位保存加法)。这需要在计算结束时额外添加
他们经常使用基数4来减少添加步骤(修改的Booth算法)。
它们通过管道传输以提高吞吐量
顺便说一句,您可能对此online simulator中的各种计算机算术算法感兴趣。