Environment Calls

Logo

Environment Calls are special higher-level useful actions that can be used in strained environments such as our bare-metal situation. They are often called System Calls. Many machines offer these functions as a means of aiding development without having to write everything from scratch. (Phew!! Of course, you can still see their implementations if you look at the syscall.s file in the kernel source code. Everything that runs in our little virtual machine is written in assembly and built the same way as your code!)

To invoke these, which are implemented by the kernel, you follow the instructions provided in the table and description sections below for the environment call you wish to use. Then you use the special ecall instruction which will call into the kernel and perform the requested action before returning to your own code.

For example, printing a number:

  li    a7, 4     # Select environment call 4 (print integer)
  li    a0, 42    # Pass in arguments using the a1 register (see the table)
  ecall           # Invoke the environment call (it will print '42')

Other environment calls may have more or no arguments. Some may provide results in various registers, typically a0. Refer to the table below for more information.

Overview

a7 Name Sets (if any) Arguments Description
1 print integer a0: integer to print Prints the integer given in a1. It does not print a newline.
4 print string a0: address of string Prints the null-terminated string given in a0. It does not print a newline.
5 read integer a0: integer read
8 read string a0: characters read a0: address of buffer
a1: maximum number of characters to read.
10 exit a0: exit code Terminates the program and powers down the machine.
30 system time a0: milliseconds since boot Gets the number of milliseconds since booting the machine. Will not be incredibly accurate.
40 set seed a0: id of generator Sets the given random number generator to the given seed.
41 random word a0: random word a0: The id of the generator to use.

Descriptions and Usage

print integer

Set a7 to 1.

Prints the given integer in a0.

  li    a7, 1     # Select environment call 1 (print integer)
  li    a0, 42    # Pass in arguments using the a0 register (see the table)
  ecall           # Invoke the environment call (it will print '42')

print string

Set a7 to 4.

Prints the given string whose address is within a0.

  li    a7, 4     # Select environment call 4 (print string)
  li    a0, str   # Pass in arguments using the a0 register (see the table)
  ecall           # Invoke the environment call (it will print 'Hello!')

.data

  str: .string "Hello!"

read integer

Set a7 to 5.

Waits for something to be typed in and parses that as an integer which it stores in a0.

  li    a7, 5     # Select environment call 5 (read integer)
  ecall           # Invoke the environment call (it will wait here until something is typed in)

  # Now, a0 is the number typed in (or your program errors if the input was not a number!)
  # Let's double the number with a shift left
  sll   a0, a0, 1

  # While a0 is still the number we care about ... let's print it out
  li    a7, 1     # Now, we will print it out using the print integer environment call
  ecall           # Prints the number (double the input) back out! (Remember, a0 is still that number!)

read string

Set a7 to 8.

Waits for something to be typed in (ends with an 'enter' press) and writes it to the buffer given in a0.

  li    a7, 8     # Select environment call 8 (read string)
  la    a0, buff  # Give it the address of our memory we want to use to write the string to
  li    a1, 99    # We can write up to 99 characters into our buffer
  ecall           # Invoke the environment call (it will wait for a line to be entered)

  # Now, our buffer in `buff` is filled with the line just typed in
  # Let's print it out again

  li    a7, 4     # Use the print string ecall
  la    a0, str   # Prints a helpful string
  ecall

  li    a7, 4     # Use the print string ecall again
  la    a0, buff  # Prints the typed in string
  ecall

.data

  buff: .fill 100, 1, 0 # Fills 100 bytes with 0s
  str:  .string "\nYou typed in: "