Parrot Virtual Machine/Parrot Assembly Language
Parrot Assembly Language
The Parrot Virtual Machine (PVM) operates on a special-purpose bytecode format. All instructions in PVM are converted into bytecode instructions to be operated on by the virtual machine. In the same way that ordinary assembly languages share a one-to-one correspondence to the underlying machine code words, so too do the Parrot bytecode words have a similar correspondence to a Parrot Assembly Language (PASM).
The PASM is very similar to traditional assembly languages, except that the instructions provide access to many of the dynamic and high-level features of the Parrot system.
Instruction Types and Operands
Internally to parrot, there are many many different instructions. Some instructions are just variations of each other with the same behavior, but different arguments. For instance, there are instructions for:
The letters after the name of the instruction specify what kinds of operands that instruction requires.
add_i_i_ic takes an integer (i) and an integer constant (ic) and returns an integer (i).
add_n_n_n takes two floating point numbers and returns a floating point number.
In PASM, when you write the following statement:
add $I0, $I1, $I2
Parrot looks up the appropriate instruction from the list,
add_i_i_i and calls it. The user sees 1 instruction, "add", but Parrot actually has multiple instructions and decides which to use automatically for you. If you type the following into Parrot:
add $P0, $I1, $I2
You will get an error message that there is no such instruction
add_p_i_i. This should help you debug your programs.
Parrot Assembly Basics
Parrot is a register-based virtual machine. There are an undetermined number of registers that do not need to be instantiated before they are called. The virtual machine will make certain to create registers as they are needed, and rearrange them as makes sense to do so. Register names are lexically scoped, so register "$P0" in one function is not necessarily the same data location as register "$P0" in another function.
All registers start with a "$" sign. Following the "$", called the "sigil", there is a letter that denotes the data type of the register, followed by the register number. There are 4 types of data items, each with a unique register character identifier. These are:
- String registers start with an "S". String registers can be named things like "$S0" or "$S100".
- Integer registers start with an "I". Integer registers can be named things like "$I0" or "$I56".
- Floating point number registers, registers which can hold a floating point number, start with a letter "N". These registers can be named things like "$N0" or "$N354".
- PMCs are advanced object-oriented data types, and a PMC register can be used to hold many different kinds of data. PMC registers start with a "P" identifier, and can be named things like "$P0" or "$P35".
A basic PASM statement contains an optional label, an instruction mnemonic, and a series of comma-separated arguments. Here is an example:
my_label: add_n $P0, $P1, $I1
In this example the add_n instruction performs addition on two registers and stores the result in a third. The values from $P1 and $I1 are added together, and the result is stored in $P0. Notice that the operands are different types. One of the arguments, and the result are both PMC registers, but the second operand is an integer and the add_n instruction is an integer instruction. Parrot will automatically handle data type conversions as necessary when performing instructions like this. The only thing that is required is that it is possible to convert between two data types. If it is possible, Parrot will handle the details. In some cases, however, automatic type conversions are not possible and in these cases Parrot will raise an exception.
PASM has few available directives.
- This directive defines the start of a new subroutine.