CPU 1001 Instruction Set Explain

Each instruction has zero/one argument.  The argument is 24-bit.  It can be an address (ads), a register (r) or a constant (n).  There are five groups of instructions: arithmetic, logic, bitwise, data movement and control.  Internally, there are 32 registers and the 1000 slots of memory that can hold both data and program. An accumulator is a "scratch pad" of the processor.  Almost all operations keep their results in AC.  Flag is one bit and is used to store the result of logical operations. 

register R[0] ... R[31]
memory  M[0].. M[1000]

Arithmetic operation

add r     ac = ac + R[r]      add
sub r     ac = ac - R[r]      substact
inc r     R[r] = R[r] + 1     increment by 1
dec r     R[r] = R[r] - 1     decrement by 1
shl r     ac = R[r] << 1      multiply by 2
shr r     ac = R[r] >> 1      divide by 2

Logical operation

the result is stored in Flag
eq r      F = ac == R[r]      equal
ne r      F = ac != R[r]      not-equal
lt r      F = ac < R[r]       less-than
le r      F = ac <= R[r]      less-than-or-equal
gt r      F = ac > R[r]       greater-than
ge r      F = ac >= R[r]      greater-than-or-equal
eqz r     F = R[r] == 0       equal-zero  
           

Bitwise operation

and r     ac = ac & R[r]      bitwise and
or r      ac = ac | R[r]      bitwise or
not r     ac = ~ R[r]         bitwise not
xor r     ac = ac ^ R[r]      bitwise exclusive or

Data move operation

mov r     ac = R[r]           move to accumulator
mvi n     ac = n              move constant to accumulator
put r     R[r] = ac           put to register
ld ads    ac = M[ads]         load from memory
st ads    M[ads] = ac         store to memoru
ldd r     ac = M[R[r]]        load defer (indirect) from memory
std r     M[R[r]] = ac        store defer (indirect) to memory

Control the flow of program

jmp ads   pc = ads               unconditional jump to ads
jf ads    if (F == 0) pc = ads   jump if false (Flag is 0) to ads
jt ads    if (F != 0) pc = ads   jump if true  (Flag is not 0) to ads
call ads  save(pc), pc = ads     jump to subroutine
ret       restore(pc)            return from subroutine
stop                             stop the execution

Simulator

The simulator will execute the program one instruction at a time.  I put a limit at 1000 instructions.  The return stack stored the return address caused by a "call" instruction.  It has the dept of 10 (only 10 nested calls).  The maximum memory is 1000.  The memory is used to store both the program and the data.  You can write quite a number of simple program using only the first ten instructions in the instruction set.

Example programs

1)  Multiply by repeat addition

pseudo code
;  s is the result, m is multiplicand, n is multiplier
   s = 0
   while( n != 0 )
      s = s + m
      n = n - 1


machine code
let r1 - m, r2 - n, r3 - s
                                           address    instruction
  mvi 11                0    4,11
  put r1                1    3,1
  mvi 3                 2    4,3
  put r2  ; m 11, n 3   3    3,2

  mvi 0                 4    4,0
  put r3                5    3,3
loop: eqz r2            6    5,2
  jt exit               7    6,13
  mov r3                8    1,3
  add r1                9    2,1
  put r3  ; s = s + m   10   3,3
  dec r2                11   7,2
  jmp loop              12   8,6
exit: stop              13   0


code: 4,11,3,1,4,3,3,2,4,0,3,3,5,2,6,13,1,3,2,1,3,3,7,2,8,6,0

2)  Find the maximum value of two values

pseudo code
; let A, B be the input, M is the maximum of A,B   

   if A > B then M = A else M = B

machine code
; let r1 - A, r2 - B, r3 - M
  mvi 10                0    4,10
  put r1                1    3,1
  mvi 20                2    4,20
  put r2 ; A 10, B 20   3    3,2
  mov r1                4    1,1
  gt r2                 5    16,2
  jt true               6    6,10
  mov r2                7    1,2
  put r3 ; M = B        8    3,3
  jmp end               9    8,12
true: mov r2            10   1,2
  put r3 ; M = A        11   3,3
end:  stop              12   0


code:  4,10,3,1,4,20,3,2,1,1,16,2,6,10,1,2,3,3,8,12,1,2,3,3,0

3)  Add 1.. 10

pseudo code
;  let s is sum, i count 1 to 10
  s = 0
  i = 0
  while i <= 10
     s = s + i
     i = i + 1


machine code
; let  r1 - s, r2 - i,  r3 - 10
  mvi 0                  0     4,0
  put r1                 1     3,1
  put r2                 2     3,2
  mvi 10                 3     4,10
  put r3                 4     3,3
loop: mov r2             5     1,2
  le r3                  6     15,3
  jf exit                7     23,13
  mov r1                 8     1,1
  add r2                 9     2,2
  put r1                 10    3,1
  inc r2                 11    11,2
  jmp loop               12    8,5
exit: stop               13    0


code: 4,0,3,1,3,2,4,3,3,3,1,2,15,3,23,13,1,1,2,2,3,1,11,2,8,5,0

4)  Find the maximum value in an array of number

How to access an element in an array?  We need to calculate "effective address". For example let ax be an array starts at the address 100, assume each element takes one 32-bit slot, the address of the element ax[2] will be the base address of ax (100) plus 2, or 102. Using the effective address storing in a register, we then load/store it by "ldd/std" instruction which perform "indirect" addressing.

;  let m be the maximum, the array be ax[.], i be the index over ax[.], assume size of array is 10.

    m = ax[0]
    i = 1
    while ( i < 10)
       if m < ax[i] then m = ax[i]
       i = i + 1

machine code
; let r1 - i, r2 - m, r3 - &ax[i], r4 - ax[i], r5 - 10
  mvi 1                 0     4,1
  put r1                1     3,1
  mvi 100  ; &ax[0]     2     4,100
  put r3                3     3,3
  ldd r3                4     26,3
  put r2  ; m = ax[0]   5     3,2
  inc r3  ; now,&ax[1]  6     11,3
  mvi 10                7     4,10
  put r5                8     3,5
loop: mov r1            9     1,1
  lt r5 ; i < 10        10    14,5
  jf exit               11    23,22
  ldd r3                12    26,3
  put r4  ; ax[i]       13    3,4
  mov r2                14    1,2
  lt r4  ;if m < ax[i]  15    14,4
  jf skip               16    23,19
  mov r4                17    1,4
  put r2  ; m = ax[i]   18    3,2
skip: inc r1            19    11,1
  inc r3 ; next ax[i]   20    11,3
  jmp loop              21    8,9
exit: stop              22    0

testing:  we initialise ax[0] = 11, ax[1] = 44, ax[2] = 22 and limit the length to 3 (r5 = 3), with the following code:
init: mvi 11
  st 100
  mvi 44
  st 101
  mvi 22
  st 102
  mvi 1
  jmp 1    ;  goto main
exit: stop


code : 8,23,3,1,4,100,3,3,26,3,3,2,11,3,4,3,3,5,1,1,14,5,23,31,26,3,3,4,1,2,14,4,23,19,
1,4,3,2,11,1,11,3,8,9,1,1,4,11,25,100,4,44,25,101,4,22,25,102,4,1,8,1,0

5) call a function (do subroutine call)
A subroutine to add 2 to r1.

machine code
  jmp main         0     8,4
add2: mov r1       1     1,1
  add r2           2     2,2
  ret              3     29,0
main: mvi 4        4     4,4
  put r1           5     3,1
  mvi 2            6     4,2
  put r2           7     3,2
  call add2        8     28,1
  stop             9     0


code: 8,4,1,1,2,2,29,0,4,4,3,1,4,2,3,2,28,1,0

Conclusion

  Programming at the level of machine code is rather simple.  However, it is tedious.  It makes the task simpler if you arrange which register to use before hand.

Exercises

1)  Find the maximum  of three values (use a lot more comparison than our example).
2)  Multiplication by "double" the multiplicand and "half" the multiplier.  This method is much faster than repeat addition but you have to take care of the last multiplication.
3) Go into an array and double all its elements.
4)  Reverse the order of elements in an array.
5)  Suppose an array is terminated by the element 0. Count how many element an array has.
6)  A challenge:  How can you write a "recursive" program (a function that calls itself)? Here is the task: Compute sum 1..n by recursion (subroutine)

pseudo code

 sum(n)
    if( n == 0 ) return 0
    else return n + sum(n-1)


 main()
    sum(10)

Prabhas Chongstitvatana
last update  10 February 2015