Assembly Commands

The Buzz Virtual Machine (BVM) is a stack machine that works with a custom assembly language. The instruction set is composed of 46 elements. Each command can be used either by writing Buzz Assembly code directly (in a .basm file); most of them, have a corresponding C-function that can be used when integrating Buzz with other software.

The table below reports both the plain assembly command and the corresponding C function, along with a brief description of the effect of a command. In the description, stack(N) stands for the N-th element on the stack. The stack-top element is stack(1); the element beneath it is stack(2), and so on. If the stack contains K elements, the bottom element is stack(K).

Command C function Description
nop No operation
done buzzvmdone(VM) | Ends the execution | | pushnil | buzzvmpushnil(VM) Pushes nil on the current stack
dup buzzvmdup(VM) | Pushes stack(1) on the current stack | | pop | buzzvmpop(VM) Removes stack(1) from the current stack
ret0 buzzvmret0(VM) | Returns from a closure call without returning a value to the caller | | ret1 | buzzvmret0(VM) Returns from a closure call and returns the current stack(1) to the caller
add buzzvmadd(VM) | Pushes the result of stack(1) + stack(2), pops operands | | sub | buzzvmsub(VM) Pushes the result of stack(1) - stack(2), pops operands
mul buzzvmmul(VM) | Pushes the result of stack(1) * stack(2), pops operands | | div | buzzvmdiv(VM) Pushes the result of stack(1) / stack(2), pops operands
mod buzzvmmod(VM) | Pushes the result of stack(1) % stack(2), pops operands | | pow | buzzvmpow(VM) Pushes the result of stack(1) ^ stack(2), pops operands
unm buzzvmunm(VM) | Pushes -stack(1), pops operand | | and | buzzvmand(VM) Pushes the result of logical stack(1) AND stack(2), pops operands
or buzzvmor(VM) | Pushes the result of logical stack(1) OR stack(2), pops operands | | not | buzzvmnot(VM) Pushes the result of logical NOT stack(1), pops operand
eq buzzvmeq(VM) | Pushes the result of stack(1) == stack(2), pops operands | | neq | buzzvmneq(VM) Pushes the result of stack(1) != stack(2), pops operands
gt buzzvmgt(VM) | Pushes the result of stack(1) > stack(2), pops operands | | gte | buzzvmgte(VM) Pushes the result of stack(1) >= stack(2), pops operands
lt buzzvmlt(VM) | Pushes the result of stack(1) < stack(2), pops operands | | lte | buzzvmlte(VM) Pushes the result of stack(1) ⇐ stack(2), pops operands
gload buzzvmgload(VM) | Pushes the global variable corresponding to string at stack(1), pops operand | | gstore | buzzvmgstore(VM) Stores stack(1) into global variable whose name is at stack(2), pop operands
pusht buzzvmpusht(VM) | Pushes an empty table on the current stack | | tput | buzzvmtput(VM) Performs t[k] = v; v is stack(1), k is stack(2)), t is stack(3); pops operands
tget buzzvmtget(VM) | Pushes t[k] on the current stack; k is stack(1)), t is stack(2); pops operands | | callc | buzzvmcallc(VM) Calls the closure at stack(1) as a normal closure
calls buzzvmcallc(VM) | Calls the closure at stack(1) as a swarm closure | | pushf CONST | buzzvmpushf(VM, CONST) Pushes a floating-point constant on the current stack
pushi CONST buzzvmpushi(VM, CONST) | Pushes a 32-bit signed integer constant on the current stack | | pushs SID | buzzvmpushs(VM, SID) Pushes a string (identified by the string id SID on the current stack
pushcn ADDR buzzvmpushcn(VM, ADDR) | Pushes the native closure at address ADDR on the current stack | | pushcc CID | buzzvmpushcc(VM, CID) Pushes the C closure identified by the id CID on the current stack
pushl ADDR buzzvmpushl(VM, ADDR) | Pushes the lambda at address ADDR on the current stack | | lload IDX | buzzvmlload(VM, IDX) Pushes the local variable at index IDX on the current stack; index count starts at 1.
lstore IDX buzzvm_lstore(VM, IDX) Stores stack(1) into the local variable at index IDX, pops operand; index count starts at 1
jump POS Sets the program counter to POS
jumpz POS If stack(1) == 0, sets the program counter to POS; pops operand
jumpnz POS If stack(1) != 0, sets the program counter to POS; pops operand

Debugging Information

To make human-readable error reporting possible, assembly code can be annotated with extra information. Debugging annotations are added to each assembly code line. To mark the beginning of the information, the character | is used; after this character, the line number, column number, and file name are reported, separated by commas. No spaces are allowed before or after the commas. Line and column counts start from 1. For example:

@__label_0
	pushs 0	|7,18,/Users/myuser/test.bzz
	pushi 2	|7,20,/Users/myuser/test.bzz
	gstore	|7,21,/Users/myuser/test.bzz

Debugging information is not mandatory for each line. In fact, the preamble of any Buzz assembly file (the part in which strings are recorded and global symbols are registered) has no associated debugging information.

Tool support
  • Debugging information is automatically generated by bzzparse upon compiling a Buzz script.
  • bzzasm takes each assembly line and uses the assembly command to produce bytecode, and the associated debugging information to produce a debugging information file.
  • bzzdeasm performs the opposite process: it takes as input a bytecode file and a debugging information file, and produces an annotated assembly code file.