previous page - PiLAR index - next page

PiLAR official logo
PiLAR is a 16-bit stack-based task-oriented microprocessor. Click here for the main documentation page.

Programming examples index:


What happens on the stack when calling a routine

Let's assume that the high-level programming language source line is "a=func(b,c)", where a is an uword, b is a long, and c is an ubyte. The calling source code will be:

  1. PUSH long b
  2. PUSH ubyte c
  3. CALL uword func
  4. POP uword a

What happens on the stack?

  1. "push" a long object: stack grows by four bytes;
  2. "push" an ubyte object: stack grows by one byte;
  3. "call" a subroutine:
  4. the remaining uword (result value) can now be popped from the stack and stored in the variables pool.

Let's also assume that the called routine just divides the two parameters and returns the value. Its code will be:

  1. LABEL func
  2. STACK long +7
  3. STACK ubyte +6
  4. CONVERT ubyte to long
  5. DIV long
  6. CONVERT long to uword
  7. UNSTACK uword +4
  8. RETURN uword 5

The two parameters are placed on the stack; the latter has to be converted to long to do the division; the result is then converted to the format of the return value and saved; the last instruction returns control clearing local stack (in this case no space is freed because no ALLOCATE instruction was issued) telling to release also the two parameters (requiring 4+1=5 bytes of stack space), keeping on the caller's stack the resulting uword only.


The common Fibonacci routine is a recursive function defined as:
fib(n) { if(n<2) return n; else return fib(n-1) + fib(n-2); }

The compiled code, for a long parameter, will be:

  1. LABEL fib
  2. STACK long +8
  3. DUPLICATE long
  4. UNSTACK long +4
  5. IMMEXPAND 2
  6. CONVERT word to long
  7. CHECK GE
  8. BRANCH true okreturn
  9. STACK long +8
  10. DEC long
  11. DUPLICATE long
  12. DEC long
  13. CALL long fib
  14. SWAP long
  15. CALL long fib
  16. ADD long
  17. UNSTACK long +4
  18. LABEL okreturn
  19. RETURN long 4

What happens:

  1. function code begins;
  2. stack the current value of n;
  3. duplicate it for later use;
  4. save it in the "return value" field (now only one "n" is on the stack);
  5. place a word=2 on the stack;
  6. expand it to long;
  7. check for greater-equal (subtract it to current value of n); now local stack is empty;
  8. skip the entire section if it was less than 2;
  9. stack the current value of n;
  10. decrement it to get "n-1" on the stack;
  11. duplicate it;
  12. decrement it, so that there are now "n-2" and "n-1" on the local stack;
  13. recursive call: fib(n-2); we then have two values ("result of fib(n-2)" and "n-1") on the local stack;
  14. swap the two values;
  15. recursive call: fib(n-1);
  16. add the two long results;
  17. place the sum in the "return value" field;
  18. this is the place where the BRANCH jumps;
  19. cleanup and exit.

The routine is just 28 bytes long.


We now will see some simple code chunks. Let's start showing:
char i; word a[60]; for(i=0; i<60; i++) a[i]=i*i+32;

Really easy:

  1. ALLOCATE 121 (60 words plus one byte)
  2. IMMEDIATE byte 0
  3. POP i
  4. LABEL cycle
  5. PUSH i
  6. IMMEDIATE 60
  7. CHECK LE
  8. BRANCH false endcycle
  9. IMMEXPAND 32
  10. PUSH i
  11. CONVERT byte TO uword
  12. DUPLICATE word
  13. DUPLICATE word
  14. MUL word
  15. ADD word
  16. PUSH i (index)
  17. ADDRESS a (obtain the real address)
  18. PLACE word (combine address/index and write out result)
  19. PUSH i
  20. INC byte
  21. POP i
  22. BRANCH cycle
  23. LABEL endcycle

Notice the "a[i]" data object set in just three instructions.

Another example: how to handle a switch/case block?
switch(i/3) { case 1: fun1(); case 5*total: fun3(); ...

Just a sequence of expression stacking followed by conditional jumps. Assuming i is a word, we just

  1. IMMEXPAND 3
  2. PUSH word i
  3. DIV word
  4. LABEL firstcase
  5. IMMEXPAND 1
  6. COND BRANCH word secondcase
  7. CALL fun1
  8. BRANCH endswitch
  9. LABEL secondcase
  10. IMMEXPAND 5
  11. PUSH word total
  12. MUL word
  13. COND JUMP word thirdcase
  14. CALL fun3
  15. BRANCH endswitch
  16. LABEL thirdcase
  17. ...
  18. LABEL defaultvalue
  19. DISCARD word
  20. ...
  21. LABEL endswitch
  22. ...

Note the DISCARD operation to get rid of the no more interesting stacked expression.


Vista da una delle torrette della rocca di San Marino

previous page - PiLAR index - home page - send e-mail - next page