2019-11-17 21:02:35 +01:00
2019-11-23 16:47:16 +01:00
2019-11-23 16:47:16 +01:00
2019-11-23 16:47:16 +01:00
2019-11-17 21:02:35 +01:00
2019-11-17 21:02:35 +01:00
2019-11-23 16:47:16 +01:00

Design

Parsing

  • First we tokenize the input (syntax check)
  • Then we interpret the input (semantics check)
  • Then we execute the input

Notation

  • [operation][number type], e.g. divi for divide (div) integer
  • %[register] for addressing registers
  • $[value] for using literals/immediate values
  • ; for end of statement (mandatory)
  • [label]: for labels
  • #[text] for comments: any text is ignored till a newline (\n) is found
  • [[%register|$value]] for accessing memory
  • Elements must be separated by whitespace character
    • Good: add $2 $5 %A;
    • Bad: add $2$5%A;

Examples

Divide register A by 5 and store the result in register A: divi %A $5 %A;

Increment B until it is 10:

# Set B to zero
addi $0 $0 %B;

loop:
addi $1 %B %B;
lti %B $10;
jmp loop;

Read the integer at memory location 1024 into register A:

seti %A [$1024];

Remember not to use spaces inside the [ brackets.

Reserved symbols

The following whitespace characters are used to separate symbols:

  • space ( )
  • tab (\t)
  • return carriage (\r)
  • newline (\n)

The following characters are used as identifiers:

  • dollar ($) for immediate (literal) values
  • percentage (%) for register identifiers
  • colon (:) for jump labels
  • semicolon (;) for statement termination
  • hash (#) for comments

All symbols are reserved keywords and can therefore NOT be used as labels.

Symbols

Directives

  • DECLARE declares the first label argument to equal the second, immediate value, argument and is used to declare a constant for the virtual machine.

Operands

  • addi add the first to the second argument and store the result in the third argument
  • subi subtract the first from the second argument and store the result in the third argument
  • divi divide the first by the second argument and store the result in the third argument
  • muli multiply the first by the second argument and store the result in the third argument
  • shli shift left the first argument by the number of positions given by the second argument and store the result in the third argument
  • shri shift right the first argument by the number of positions given by the second argument and store the result in the third argument
  • seti set the first register argument to the second argument
  • int calls the interrupt specified by the first (integer) argument

Control Flow

  • jmp jump to the label given by the first argument
  • lti execute next statement if argument 1 is less than argument 2 else skip the next statement
  • gti execute next statement if argument 1 is greater than argument 2 else skip the next statement
  • eqi execute the next statement if argument 1 is equal to argument 2 else skip the next statement

Memory

  • popi pops the first value on the stack into the register specified as the first argument
  • pushi pushes the value on the stack from the register or immediate value as the first argument

Interupts

  • [0..9] Output to STDOUT
    • 0 put value of register A as ASCII character on stdout
    • 1 put value of register A as decimal integer on stdout
    • 2 put value of register A as hexadecimal integer on stdout
    • 3 put the string pointed at by register A for the amount of characters defined by register B on stdout
Description
No description provided
Readme 173 KiB
Languages
C++ 99.8%
Makefile 0.2%