Skip to content

Variables and Constants

Joachim Stolberg edited this page Jun 19, 2024 · 27 revisions

vm16 CPU registers are 16-bit wide. The CPU memory is also organized in 16-bit words. 8-bit addressing is not supported. Therefore, the compiler does without different data types and uses the keyword var for all variables.

var

The keyword var is used for the creation (declaration) of each variable. Variable declarations outside of a function are globally visible and can be used in all files of your program. Variable declarations outside of a function with the keyword static are only visible in the current file. Variable declarations inside a function are only locally visible and get lost when the function ends or returns. To avoid naming conflicts, use function local or static variables as far as possible. Global variables should be given names that are as unique as possible.

The default type for variables is "unsigned 16 bit". Variables can store values from 0 to 65535. Other data types are not supported.

Syntax:

var myVar;           // Will be initialized with the value zero.
var Counter = 12;    // Will be initialized with the value 12.
static var State;    // Static variable, only visible and usable within the current file.

Values like in var Counter = 12 can be written as decimal, hexadecimal and octal value.

var Counter = 0377;     // Octal numbers have a leading '0'.
var Counter = 511;      // Decimal number.
var Counter = 0x1FF;    // Hexadecimal numbers have a leading '0x'.

All three figures have the same value 511.

Examples:

import "sys/stdio.asm"

var MaxVal = 32;

func main() {
  var i;

  for(i = 0; i < MaxVal; i++) {
    putnum(i);
  }
  return;
}

const

The const keyword stands for constant. Constants are initialized with numbers and can't be changed (can be seen as "read-only" variables). To avoid magic numbers in your program define constants with meaningful names instead. Constants can only be defined outside of a function.

import "sys/stdio.asm"

const MAX_VAL = 32;

func main() {
  var i;

  for(i = 0; i < MAX_VAL; i++) {
    putnum(i);
  }
  return;
}

static

The keyword static is used for the creation of file local variables and constants. These variables are only visible and useable in the file in which they are created.

Syntax:

static var Counter = 12;    // Will be initialized with the value 12.
static var State;           // Will be initialized with the value zero.
static const MAX1 = 100;

string

Text string have to be written in quotation marks, like "Hello". Strings are always null-terminated. Two types of strings are supported:

  1. array of characters. Syntax: var s1[] = "text";
  2. pointer to a string. Syntax: var s2 = "text";

The first is easier to understand. The string in this case is an array of characters. s1 is the address of the first character of the string. These strings have to be created (declared) globally, outside of functions (like arrays).

Pointer to strings are more like normal variables. That means not the string itself, but the address of the string is stored in the variable. An advantage of pointers is that they can be created (declared) as local variable inside a function.

Examples:

import "sys/stdio.asm"

var str1[] = "Hello1";                                // automatically zero terminated
var str2[4] = {'He', 'll', 'o2', '\0'};               // explicit zero terminated
var str3[7] = {'H', 'e', 'l', 'l', 'o', '3', '\0'};   // 8 bit characters
var str4 = "Hello4";

func main() {
  var str5 = "Hello5";

  putstr(str1);
  putstr(str2);
  putstr(str3);
  putstr(str4);
  putstr(str5);
  return;
}

Please note: The CPU does not support 8-bit characters. Therefore, up to 2 characters are always stored in a word. The length of the string "test" is two words, the length of the string "hello" is 3 words.

(see String for functions to manipulate strings and arrays)

character

Since variables are always 16 bits in size, one or two characters can be stored in a variable. Characters have to be written in single quotes, like 'A' or 'BC'.

Examples:

import "sys/stdio.asm"

var ch1 = 'He';

func main() {
  var ch2 = 'll';

  putchar(ch1);
  putchar(ch2);
  putchar('o');
  return;
}

array

An array is a collection of words that are accessed with an index number. Copil supports only one-dimensional arrays. Using there kind of arrays is relatively straightforward.

Creating (Declaring) an Array:

All of the methods below are valid ways to create (declare) an array.

var myVals[6];
var myNums[] = {2, 4, 8, 3, 6};
var arr1[5] = {2, 4, 8, 3, 2};

const SIZE = 10;
var arr2[SIZE];

func foo() {
  var a[2];  // The only way to declare function-local arrays
  ...
}

You can declare an array without initializing it as in myVals. In myNums we declare an array without explicitly choosing a size. The compiler counts the elements and creates an array of the appropriate size. Finally you can both initialize and size your array, as in arr1.

The maximum size of an array is 2048 elements.

Accessing an Array

Arrays are zero indexed, that is, referring to the array initialization above, the first element of the array is at index 0, hence myVals[0] = 2, myVals[1] == 4, and so forth.

It also means that in an array with ten elements, index nine is the last element. For this reason you should be careful in accessing arrays. Accessing past the end of an array (using an index number greater than your declared array size - 1) is reading from memory that is in use for other purposes. Reading from these locations is probably not going to do much except yield invalid data. Writing to random memory locations is definitely a bad idea and can often lead to unhappy results such as crashes or program malfunction. This can also be a difficult bug to track down.

To assign a value to an array:

arr1[0] = 10;

To retrieve a value from an array:

var x = myNums[4];