以太坊虛擬機算術運算指令
EVM總共定義了11條算術運算指令,見下表:函數
這些指令從棧頂彈出兩到三個元素,進行相應計算,而後把結果推入棧頂。參與計算的元素和結果均被解釋爲按二的補碼編碼的整數。若是計算結果(假設爲x)溢出(超出2^256),則最終的結果x’取值x % 2^256(%表示取模運算,^表示指數運算)。ui
下面是算術運算指令的操做碼分佈圖: 編碼
ADD、MUL、SUB、DIV、SDIV、MOD、SMOD、EXP
這8條指令操做方式比較相似,從棧頂彈出兩個元素,進行計算,而後把計算結果推入棧頂。因爲採用二的補碼錶示整數時,加法、減法和乘法運算不用考慮符號位,因此加法、減法和乘法運算都只有一條指令。整除和取模運算須要考慮符號位,因此各有兩條指令。指數運算只操做無符號整數。以ADD指令爲例,下面是它的操做示意圖: 3d
ADDMOD和MULMOD
MULMOD指令依次從棧頂彈出x、y、z三個數,先計算x和y的乘積(不受溢出限制),再計算乘積和z的模,最後把結果推入棧頂。假定乘積不會溢出,那麼MULMOD(x, y, z)等價於x * y % z,下面是MULMOD指令的操做示意圖: code
ADDMOD指令和MULMOD指令相似,只不過把乘法換成了加法。下面是ADDMOD指令的操做示意圖: blog
SIGNEXTEND
SIGNEXTEND指令從棧頂依次彈出k和x,並把x解釋爲k+1(0 <= k <= 31)字節有符號整數,而後把x符號擴展至32字節。好比x是二進制10000000,k是0,則符號擴展以後,結果爲二進制1111…10000000(共249個1)。下面是SIGNEXTEND指令的操做示意圖: 編譯器
實例分析
ADD、MUL、SUB、DIV、SDIV、MOD、SMOD、EXP指令與Solidity語言裏的+、*、-、/、%、** 運算符直接對應。ADDMOD指令對應addmod()函數,MULMOD指令對應mulmod()函數。暫時尚未搞清楚SIGNEXTEND指令的用法,等之後再補充。下面的Solidity代碼演示了EVM算術運算指令的具體應用:虛擬機
// arith_demo.sol
pragma solidity ^0.4.24;it
contract C {io
function test() public view {
int s1; int s2; int s3;
uint u1; uint u2; uint u3;
uint k;
u3 = u1 + u2; // ADD
u3 = u1 * u2; // MUL
u3 = u1 - u2; // SUB
u3 = u1 / u2; // DIV
s3 = s1 / s2; // SDIV
u3 = u1 % u2; // MOD
s3 = s1 % s2; // SMOD
u3 = u1 ** u2; // EXP
u3 = addmod(u1, u2, k); // ADDMOD
u3 = mulmod(u1, u2, k); // MULMOD
}
}
讀者能夠運行solc --asm --opcodes arith_demo.sol命令觀察編譯器生成的字節碼。
總結本文介紹了EVM算術運算指令,下一篇文章將介紹EVM按位運算指令。