Variables, Subroutines, and FunctionsIndex

Introduction

The software libraries include a variety of TEA subroutines and functions.  However, there are times when a user may wish to write custom procedures using VM opcodes.  To do so, it is necessary to understand the subroutine and function call conventions used by the TEA compiler.

Variables

All variables of char type, whether signed or unsigned are stored as a single byte.  All variables of int type, whether signed or unsigned are stored as two bytes.  When storing them on the stack, the most significant byte (MSB) is always pushed before the least signficant byte (LSB).  When an int is stored in the scratchpad or passed in a command, the MSB always comes before the LSB.  Since the MSB comes first and is stored at a lower memory index, the Stem uses a "big endian" storage convention.

Subroutines

A subroutine takes a number of input parameters but does not return a value.  The input parameters are passed by-value, which means their values are copied directly onto the stack when the routine is called.  There are no pointers in TEA.  A subroutine may have local variables which must also be stored on the stack.  The number of input parameters and local variables is limited by the amount of free stack space.

An example subroutine is listed below.  It has two input parameters and one local variable.  The asm block contains VM instructions .

When executing a subroutine, the input parameters go on the stack first in the order in which they are declared.  The call instruction pushes the return address bytes to the stack and branches to the subroutine.  Once inside the subroutine, any local variables are stored on the stack in the order in which they are declared.  Uninitialized local variables are initialized to "-1" by default.  Calling the example routine listed above requires seven stack bytes: three for the input parameters, two for the return address, and two for the local variable.  Prior to execution of the instructions in the asm block, the top seven stack btyes will contain:

n (high) n (low) c return addr. (high) return addr. (low) var1 (high) var1 (low)

If n=0x0320, c=0x14, and the return address is 0x0120, the values in the top seven stack bytes will be:

0x03 0x20 0x14 0x01 0x20 0xFF 0xFF

The TEA compiler creates code that does this parameter passing and local variable allocation automatically.  The user may write code within the asm block that accesses the input parameters and local variables.  After the subroutine completes its task, the VM will pop the local variables off the stack, branch to the return address, and discard the input parameters.  This clean-up process is also automatic.

Functions

A function takes a number of input parameters and returns a value.  As with subroutines, the input parameters are passed by-value.  Parameter passing and local variable allocation also works the same way.  Unlike subroutines, functions require a place holder in the stack for the return value.  Furthermore, the compiler requires an explicit return statement for each function.  Because of this, the user must declare a local variable to hold a temporary return value and use the TEA return statement to pass the result.

An example function is listed below.  It has one input parameter and two local variables.  The asm block contains VM instructions .

When executing a function, the first thing to go on the stack is a place holder for the return value.  Calling the example routine listed above requires nine stack bytes: two for the return value place holder, one for the input parameter, two for the return address, and four for the local variables.  Prior to execution of the instructions in the asm block, the top nine stack btyes will contain:

int (high) int (low) c return addr. (high) return addr. (low) result (high) result (low) var1 (high) var1 (low)

If c=0x24 and the return address is 0x024A, the values in the top nine stack bytes will be:

0xFF 0xFF 0x24 0x02 0x4A 0xFF 0xFF 0x00 0x00

The result variable is unitialized so it is set to "-1" by default.  The return value place holder is also set to "-1" by default.  The var1 variable is initialized to "0".  The code in the asm block must write its output to the result variable for the function to work properly.  At function completion, the return statement writes the return value into the place holder.  Then the VM will pop the local variables off the stack, branch to the return address, and discard the input parameters.  The return value will be on top of the stack.

The "main" Routine

A TEA program must have one main function declaration.  This declaration defines the start point for the program.  It also defines the return type and how many bytes must be passed as input parameters.  The return type must be void, char, or int.  The input parameters must be declared as char or int types.  They can be declared with or without the unsigned modifier.  The main routine is very similar to any other type of routine.  When a program begins execution, a placeholder for the return type is pushed onto the stack.  If the return type is void, no placeholder is pushed.  Then the input data, if any, is pushed onto the stack in the order in which it is declared.  Any variables declared as globals will be pushed onto the stack after the return value placeholder and input data.  This is the only difference between stack initialization for the main routine and other routines.

Global Variables

Local variables are declared within the routines where they are used and discarded upon exiting the routine.  Global variables are declared at the beginning of a program outside of all the routines.  They are available to all routines and are not discarded until the program terminates.  Unlike local variables, global variables are always stored at a fixed location in the stack.  When a program begins execution, initializers for global variables are pushed onto the stack after placeholders for any return value bytes and any input parameter bytes.  The following program has two global variables:

This routine returns an int which is 2 bytes and expects an int and char as input which is a total of 3 bytes.  This means that global variables will start at byte 5 from the bottom of the stack.  Bytes 0,1 on the stack are the return value placeholder.  Bytes 2,3 hold the value of n.  Byte 4 holds the value of c.  Bytes 5,6 hold the value of g1.  Bytes 7,8 hold the value of g2.

Strings

The TEA language supports literal strings used as parameters in a function of subroutine call.  A string is stored as a sequence of bytes followed by a final size byte.  Unlike int and char variables whose size is fixed, the size of a string is not known at run time.  This makes writing routines with string inputs much more complicated.  The size byte of an input string must be used to calculate offsets to any other parameters that may be stored farther down in the stack.

Writing Code

The user must be careful when writing routines that use VM opcodes.  Using this technique for anything other than small routines is not recommended.  It is very easy to corrupt the stack.  When writing a procedure that uses VM opcodes, it is a good idea to write the stack data for the procedure call on a piece of paper, then trace the effect of each operation.  Tracking the contents of the stack is essential for writing a routine that works.


version: 1.0, build 80903
© Copyright 1994-2008 Acroname, Inc., Boulder, Colorado.  All rights reserved.