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
instruction which will call into the kernel and perform the requested action before returning to your
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
Refer to the table below for more information.
|a7||Name||Sets (if any)||Arguments||Description|
||Prints the integer given in
||Prints the null-terminated string given in
||Terminates the program and powers down the machine.|
||Gets the number of milliseconds since booting the machine. Will not be incredibly accurate.|
||Sets the given random number generator to the given seed.|
a7 to 1.
Prints the given integer in
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')
a7 to 4.
Prints the given string whose address is within
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!"
a7 to 5.
Waits for something to be typed in and parses that as an integer which it stores in
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!)
a7 to 8.
Waits for something to be typed in (ends with an 'enter' press) and writes it to the buffer given in
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: "