2

I'm constructing an implementation of Ben Eater's 8 bit computer and the claim at the end is that it will be made turing complete by adding a conditional jump instruction. If this is true, then it should be possible to execute logical operators such as AND, OR, NOT... etc. using the ALU which does only addition and subtraction.

How would one implement NAND or NOR (universal gate operators) using only addition or subtraction? Is it even possible to do this given that the machine has 16 bytes of RAM and 2 bytes of registers?

dedek
  • 7,981
  • 3
  • 38
  • 68
rjm27trekkie
  • 284
  • 3
  • 11
  • 1
    `0-x` is `~x + 1` (using 2's complement or unsigned). So you can rearrange that to give you bitwise NOT. For everything else, you might be stuck only handling one-bit booleans per register (in the high bit, so carry-out goes away and thus add is the same as add-without-carry, aka XOR). – Peter Cordes Mar 10 '18 at 01:30
  • 1
    The claim that a conditional branch would make it Turing complete would only be true if space was unlimited, or at least not so limited. A computer with an [instruction-set with only one instruction](https://en.wikipedia.org/wiki/One_instruction_set_computer) (e.g. subtract and branch on less-or-equal) can compute any problem that fits in its memory, but *much* more slowly than a normal CPU. e.g. it may take a *lot* of code to do something simple, and not be possible to use compact storage for bitmaps. 16 bytes may be too small to implement most interesting operations with add/sub and jcc. – Peter Cordes Mar 10 '18 at 01:34
  • interesting thought on the rearrange of 2's complement subtraction. I will try to implement that when I finish the build of ben's machine (ETA 2 months since I have to leave this at home when I go back to school) – rjm27trekkie Mar 10 '18 at 08:09
  • Is there no simulator for that architecture? That would be useful for testing software. – Peter Cordes Mar 12 '18 at 06:33
  • SAP-1 simulator? not that I know of – rjm27trekkie Mar 14 '18 at 20:13

1 Answers1

1

I think the 16 byte RAM is the limiting factor, but in general it's possible to implement any logical function using an ALU with just an adder. The trick is to get away from thinking about things at the bit level and towards thinking of using the full instruction set (however limited it might be) to write a subroutine or mini-program to do the thing we want.

For instance, we could create a 2 bit NOR operation using a 16-element look-up table with the following pseudo-assembly. Assume A and B are 2-bits numbers, A1A0 and B1B0, and there exists in memory a 16-element array called nor_array defined as { 0b11, 0b10, 0b01, 0b00, 0b10, ... }.

add a, a, a           // A = A + A, this is basically A = 2*A which effects a left shift
add a, a, a           // Same, only now A is equal to the original A * 4
add a, a, b           // A = A + B. A now has the original value of A in position [3,2]
                      // and the original value of B in position [1,0]
load a, nor_array[a]  // Load A with the value in memory at the nor_array base addr + A

Notice how the elements of nor_array are set equal to the 0th and 2nd bits of the array index nor'd together and the 1st and 3rd bits nor'd together.

nor_array[0000] = 0b11 // 0 NOR 0 = 1 ; 0 NOR 0 = 1
nor_array[0001] = 0b10 // 0 NOR 0 = 1 ; 0 NOR 1 = 0
nor_array[0010] = 0b01 // 0 NOR 1 = 0 ; 0 NOR 0 = 1
nor_array[0011] = 0b00 // 0 NOR 1 = 0 ; 0 NOR 1 = 0
nor_array[0100] = 0b10 // 0 NOR 0 = 1 ; 1 NOR 0 = 0
...

So A and B, together, define 16 total unique input combinations and we can effect a NOR operation by merely looking up in memory a value which we've pre-computed to be the result of a NOR operation between A and B. We can effect any logical operation on 2-bit numbers in this way and I believe that it's possible to extend those little subroutine to also be able to implement logical operations on arbitrarily long values of A and B by just shifting the operands in such a way as to build up the final result 2-bits at a time.