Shift Right Logical from just ADD and NAND?

故事扮演 提交于 2019-12-13 21:20:59

问题


I'm making a multiplier in a very simple assembly language in which I have BEQ, NAND, and ADD to create a SRL. I also have to keep the multiplier under 50 lines (16 used thus far) so hopefully the solution can be thrown in a loop.

EDIT: My question is how can I implement an SRL with just a NAND and an ADD

Had an idea although it is very inefficient, maybe someone can improve it:

Decrement say, a, by 1. Store that value in b. Add b and b and store in c. Beq c with a, if it's true then b is half of a, aka srl. Only problem is it would have to loop thousands of times in some cases. Still open to other ideas.


回答1:


You don't really need a right shift to implement multiplication. See how this can be done, sample code in C:

#include <stdio.h>

typedef unsigned char uint8;
typedef unsigned short uint16;

uint16 Mul8x8(uint8 a, uint8 b)
{
  int cnt;
  uint16 prod = 0;

  for (cnt = 8; cnt > 0; cnt--)
  {
    prod += prod;

    if (a & 0x80)
      prod += b;

    a += a;
  }

  return prod;
}

const uint8 Multipliers[][2] =
{
  { 0x00, 0x01 },
  { 0x01, 0x00 },
  { 0x33, 0x10 },
  { 0x11, 0x0C },
  { 0x0F, 0x0F },
  { 0x80, 0x80 },
  { 0xFF, 0xFF },
};

int main(void)
{
  int i;

  for (i = 0; i < sizeof(Multipliers) / sizeof(Multipliers[0]); i++)
  {
    uint8 a = Multipliers[i][0];
    uint8 b = Multipliers[i][1];

    uint16 p = a * b;
    uint16 p2 = Mul8x8(a, b);

    printf("0x%02X * 0x%02X = 0x%04X %c= 0x%04X\n",
           a, b, p, "!="[p == p2], p2);
  }

  return 0;
}

Output ([ideone])(http://ideone.com/NwsykN)):

0x00 * 0x01 = 0x0000 == 0x0000
0x01 * 0x00 = 0x0000 == 0x0000
0x33 * 0x10 = 0x0330 == 0x0330
0x11 * 0x0C = 0x00CC == 0x00CC
0x0F * 0x0F = 0x00E1 == 0x00E1
0x80 * 0x80 = 0x4000 == 0x4000
0xFF * 0xFF = 0xFE01 == 0xFE01



回答2:


Here is a code that uses only the operations you have (you need 2 NANDs for AND and BEQ around jump for BNE).

If you really need right shift, you can use the same kind of loop with test and set instead of shift and add. It will take N-1 iterations to shift N bits.

#include <stdio.h>

unsigned mult(unsigned x, unsigned y)
{
  unsigned test = 1, ans = 0;
next:
  if ((test & x) == 0) goto skip;
  ans += y;
skip: 
  y += y;
  test += test;
  if (test != 0) goto next;
  return ans; 
}

int main(void)
{
  unsigned x, y;
  while (1) {
    printf("Operands: ");
    if (scanf("%u%u", &x, &y) != 2) break;
    printf("Result: %u\n", mult(x, y));
  }
  return 0;
}



回答3:


Right shift can be accomplished by two bit masks: out_bit=1, in_bit=1<<RSHIFT by copying bits addressed by in_bit mask to the position addressed by out_bit mask -- just like one would shift arrays of bytes.

while (in_bit > 0) {
   if (word & in_bit) out_word+=out_bit;
   in_bit+=in_bit; out_bit+=out_bit;
}

To operate with NAND, ie. ~(a & b), there's an option to

do { 
   if (~(word & in_bit) == -1) { 
      out_word+=out_bit; 
   }
   in_bit+=in_bit; out_bit+=out_bit;
} while (!(in_bit==0));

Now there are just operators ADD / NAND.




回答4:


In order to implement multiplier, you need logical shift left, not shift right. Shift left is simply multiplying by 2. It can be implemented by adding the value by itself:

 a = a + a  ; this will produce the value shifted left. 

Shifting right is not so obvious though.



来源:https://stackoverflow.com/questions/14825123/shift-right-logical-from-just-add-and-nand

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!