MicroBlocks code is executed by a simple interpreter or virtual machine (VM) running on the microcontroller board. The instructions for this virtual machine are 32-bits consisting of an 8-bit operation (opcode) and a 24-bit operand:
<operand (24 bits)><opcode (8-bits)>
The opcode tells the virtual machine what to do. The operand is used to in different ways by different opcodes. For example, it can be used to encode constant values or jump offsets. Some opcodes don't use the operand at all, but both the interpreter and the compiler are simplified by using the same instruction format for all opcodes.
The interpreter is a stack machine. To execute a given opcode, its arguments (i.e. the values of any parameters) are first pushed onto the stack, then the code for the opcode is run. That code pops any arguments off the stack and, optionally, pushes a return value onto the stack.
For example, the instructions for
set user LED <true> are:
pushImmediate true // push the boolean value 'true'
setLEDOp // pop 'true' off the stack and set the state of the user LED to it
The instructions for
set user LED (tilt-x < 10) are:
mbTiltX // pushes the value of the tilt X sensor
pushImmediate 10 // pushes the number 10
lessThan // remove the two arguments and pushes true if tilt-x is less than 10
setLEDOp // pop a boolean value and and set the state of the user LED to it
MicroBlocks appears to run many scripts at the same time, but that is an illusion. The virtual machine actually runs a few instructions of one script, then a few instructions of the next script, and so on. It only executes one script at a time, but switches between those scripts (or "tasks") so quickly that they appear to be running simultaneously.
Unlike many programming languages, MicroBlocks can only switch to the next task at certain well-defined points in the code: at the end of a loop or at an instruction that explicitly waits, such as
wait 10 milliseconds. This avoids many of the concurrency issues (or race conditions) that one encounters in other languages. It also means advanced users can implement their own higher-level concurrency mechanisms (e.g. locks, semaphores, or monitors) in MicroBlocks because a test followed by some action such as setting a flag cannot be interrupted partway through by another MicroBlocks task. Such uninterruptible sequences are sometimes called critical sections. In MicroBlocks, every command sequence that does not contain a loop or a block that explicitly waits is an implicit critical section.
Between running user scripts, the MicroBlocks virtual machine also takes care of system chores. For example, it checks for incoming commands from the programming environment when the board is tethered. On some devices, it also performs additional system tasks. For example, on the BBC micro:bit the virtual machine periodically updates the 5x5 LED display.
The MicroBlocks VM communicates with IDEs and other types of software (such as the Mozilla Web of Things gateway) by means of a simple serial protocol.
You can find specifications for this protocol here.