Examples
EVM ADD¶
Let’s take the EVM ADD opcode as our first starting example:
opADD:
SP - 2 :JMPN(stackUnderflow)
SP - 1 => SP
$ => A :MLOAD(SP--)
$ => C :MLOAD(SP)
; Add operation with Arith
A :MSTORE(arithA)
C :MSTORE(arithB)
:CALL(addARITH)
$ => E :MLOAD(arithRes1)
E :MSTORE(SP++)
1024 - SP :JMPN(stackOverflow)
GAS-3 => GAS :JMPN(outOfGas)
:JMP(readCode)
Here is a detailed explanation of how the ADD opcode gets interpreted. Recall that at the beginning, the stack pointer is pointing to the next “empty” address in the stack:
-
First, we check if the stack is filled “properly” in order to carry on the ADD operation. This means that, as the ADD opcode needs two elements to operate, it is checked that these two elements are actually in the stack:
SP - 2 :JMPN(stackUnderflow)If less than two elements are present, then the
stackUnderflowfunction gets executed. -
Next, we move the stack pointer to the first operand, load its value and place the result in the
Aregister. Similarly, we move the stack pointer to the next operated, load its value and place the result in theCregister.SP - 1 => SP $ => A :MLOAD(SP--) $ => C :MLOAD(SP) -
Now its when the operation takes place. We perform the addition operation by storing the value of the registers
AandCinto the variablesarithAandarithBand then we call the subroutineaddARITHthat is the one in charge of actually performing the addition.A :MSTORE(arithA) C :MSTORE(arithB) :CALL(addARITH) $ => E :MLOAD(arithRes1) E :MSTORE(SP++)Finally, the result of the addition gets placed into the register
Eand the corresponding value gets placed into the stack pointer location; moving it forward afterwise. -
A bunch of checks are performed. It is first checked that after the operation, the stack is not full and then that we do not run out of gas.
1024 - SP :JMPN(stackOverflow) GAS-3 => GAS :JMPN(outOfGas) :JMP(readCode)
Last but not the least, there is an instruction indicating to move forward to the next instruction.