Wasm Introduction (Part 5): Control Instructions

CoinEx Smart Chain
5 min readMar 9, 2020

--

Written by the CoinEx Chain lab, this article is the fifth one of the Wasm Introduction series and introduces Control Instructions. CoinEx Chain is the world’s first public chain exclusively designed for DEX, and will also include a Smart Chain supporting smart contracts and a Privacy Chain protecting users’ privacy.

There are a total of 11 WebAssembly(referred to as Wasm) control instructions, of which unreachableinstruction (opcode 0x00) and nopinstruction (opcode 0x01) are relatively simple and thus will be omitted from this series. We have introduced callinstruction (opcode 0x10) in the previous article, and will provide more information about the call_indirectinstruction (opcode 0x11) next time. This article focuses on 7 instructions, i.e. block(opcode 0x02), loop(opcode 0x03), if(opcode 0x04), br(opcode 0x0C), br_if(opcode 0x0D), br_table(opcode 0x0E), and return(opcode 0x0F).

block

The effect of block instruction is equivalent to a parameterless inline function call. The return value type of the function, which is the result type of the block instruction (referred to as rt in the diagram below), is encoded in the first immediate argument of the instruction. The function's instructions (possibly many) are encoded and stored in the second immediate argument. The block instruction must end with end instruction (opcode 0x0B). Since end instruction and else instruction (opcode 0x05) to be described later only serve as a marker and have no execution effect, these two instructions are not counted in the control instructions.

The Wasml.0 specification stipulates that block instruction cannot have more than one result, so rt can be represented by one byte: 0x40 indicates no result, 0x7F indicates i32 type, 0x7E indicates i64 type, 0x7D indicates f32 type, and 0x7C indicates f64 type. According to the discussion, when the block instruction is executed, it does not use any operand that already exists on the stack. After the execution is completed, an operand may be left on the top of the stack. The following diagram shows how block instruction works:

Here is a very simple WATexample that shows the use of the block instruction:

loop

loop instructions are very similar to block instructions. The only difference is how to jump out of the control block, which will be discussed further in the introduction of br instructions later. The following diagram shows the the difference of jumps:

if

Like block instructions, if instructions are similar to an inline function. There are two main differences. First, the if 'inline function' takes an i32 type parameter. Second, the if 'inline function' has two pieces of code (two branches), separated by an else instruction. When the if instruction is executed, the i32 type parameter is popped from the top of the stack first. If the parameter value is not equal to 0, the code of first branch is executed; otherwise the code of second branch is executed. The following diagram shows how if instruction works:

You can also omit the elsebranch of the ifinstruction, but in this case the ifinstruction cannot have any results. The following is a schematic diagram of the if instruction when the else branch is omitted:

br

br instructions (which can be understood as break, or branch) can perform an unconditional jump. Unlike the JUMP instruction in traditional assembly language, the br instruction cannot jump to arbitrary position, but can only jump out (break for block and if instructions, and continue for loop instruction, which will not be emphasized later.) of control blocks generated by other control instructions. br instructions take an immediate argument of type u32 (a 32-bit unsigned integer) that specifies the number of layers to jump out: 0 means to jump out of the current block, 1 means to jump out of the Layer-2 block, and so on. Here is a WAT example showing the use of nested blocks and br instructions:

br_if

The br_if instruction pops an operand of type i32 from the top of the stack. If the value of the operand is 0, no jump is performed; otherwise the br logic is executed. The following diagram shows how br_if instruction works:

Please note that the loopinstruction does not automatically loop, and must be used in conjunction with jump instructions such as br.

br_table

Whether it is a bror br_ifinstruction, there is only one immediate argument, which can specify a jump depth. The br_tableinstruction breaks this limitation. It can take N + 1 immediate arguments and specify N + 1 jump depths. When the br_tableinstruction is executed, an operand nof i32type is popped from the top of the stack. If nis less than or equal to N, it jumps by the nth depth; otherwise it jumps by the last depth. The following diagram shows how br_tableinstruction works:

return

The return instruction can be considered a special form of the br instruction: it directly jumps out of the outermost loop (that is, the entire function). The return instruction has no immediate argument. The following WAT example shows how to implement switch-case statements in high-level languages such as Go with block, br_table, and return instructions:

If the select3()function defined in the above example is translated into Go language code, it should be as follows:

--

--

CoinEx Smart Chain
CoinEx Smart Chain

Written by CoinEx Smart Chain

A public chain built for the decentralized exchange. Website: www.coinex.org Telegram: t.me/CoinExChain

No responses yet