solidity中有些特殊功能如果直接利用solidity来实现很麻烦甚至是根本不能实现的,这时需要借助于底层的嵌入汇编来实现。
本附录收录了常见的嵌入汇编操作码,可以作为日常工作的快速参考。
1 算术运算相关
add(x, y)、sub(x, y)、mul(x, y)、add(x, y)、mod(x, y)、exp(x, y)
分别计算x+y、x-y、x*y、x/y、x%y、x的y次方
addmod(x, y, m)、mulmod(x, y, m)
分别计算任意精度的(x + y) % m、(x * y) % m
sdiv(x, y)、smod(x, y)
计算x/y和x%y,其中x为用二进制补码表示的有符号数
2 比较运算相关
lt(x, y)、gt(x, y)、eq(x, y)
分别为小于、大于和等于的比较运算,如果满足条件则为1否则为0
slt(x, y)、sgt(x, y)
分别为小于和大于的有符号数比较运算,如果满足条件则为1否则为0,其中x为用二进制补码表示的有符号数
iszero(x)
判断指定值是否为零,如果满足条件则为1否则为0
3 位运算相关
not(x)
按位取反
and(x, y)、or(x, y)、xor(x, y)
分别为按位进行与、或和非运算
byte(n, x)
取变量x的第n个字节
4 跳转与终止运行相关
jump(label)、jumpi(label, cond)
分别为无条件跳转到指定位置和有条件跳转到指定位置
pc
程序计数器代表当前代码位置
return(p, s)
终止程序运行并返回值mem[p..(p+s))
returndatasize
返回数据大小
returndatacopy(t, f, s)
从返回数据中f开头的地址处拷贝s字节到地址t开头的位置
stop
终止程序运行,效果与return(0,0)一样
revert(p, s)
终止程序运行,回滚对状态变量的修改并返回值mem[p..(p+s))
selfdestruct(a)
终止程序运行,销毁当前合约并把剩余资金返还给a
invalid
终止程序运行
5 变量与参数存取相关
pop(x)
从栈中弹出之前x入栈的值
dup1 ... dup16
将第nth个储存槽的值拷贝到栈顶
swap1 ... swap16
将栈顶值和第nth个储存槽的值交换
mload(p)、sload(p)
分别读取变量mem[p..(p+32))和storage[p]
mstore(p, v)、sstore(p, v)
分别保存变量mem[p..(p+32)) := v 和storage[p] := v
mstore8(p, v)
保存变量mem[p..(p+32)) := v & 0xff,只修改其中一个字节
msize
储存空间上限,或最大存储索
caller
函数调用者
callvalue
函数时携带的eth资金,wei为单位
calldataload(p)
读取从位置p开始的32字节参数
calldatasize
调用参数的字节长度,包括开头4字节的函数签名
calldatacopy(t, f, s)
从调用参数数据中f开头的地址处拷贝s字节到地址t开头的位置
6 合约相关
codesize
当前合约可执行代码大小
codecopy(t, f, s)
从代码中f开头的地址处拷贝s字节到地址t开头的位置
extcodesize(a)
指定地址可执行代码大小
extcodecopy(a, t, f, s)
从指定地址代码中f开头的地址处拷贝s字节到地址t开头的位置可执行代码大小
address
当前合约的地址
balance(a)
以wei为单位的指定账户的余额
create(v, p, s)
用mem[p..(p+s))处的代码动态创建合约并发送以wei为单位数量为v的资金
create2(v, n, p, s)
用地址为keccak256(n.keccak256(mem[p..(p+s)))处,代码为mem[p..(p+s))代码动态创建合约并发送以wei为单位数量为v的资金,返回新合约地址
call(g, a, v, in, insize, out, outsize)
对应合约外部调用调用地址为a除的合约,输入参数为mem[in..(in+insize)),允许执行的汽油上限为g,并发送以wei为单位数量为v的资金,输出参数存储在mem[out..(out+outsize)),执行成功返回1否则返回0
call(g, a, v, in, insize, out, outsize)
对应合约外部调用调用地址为a除的合约,输入参数为mem[in..(in+insize)),允许执行的汽油上限为g,并发送以wei为单位数量为v的资金,输出参数存储在mem[out..(out+outsize)),执行成功返回1否则返回0
callcode(g, a, v, in, insize, out, outsize)
和call调用一样但不执行上下文的切换,保持caller和callvalue不变
7 杂项指令
logN(p, s, [t1, t2,…,tn])
底层日志函数日志数据为mem[p..(p+s)),并且可以携带最多4个日志主题(包括index参数和事件签名)
gasprice、gaslimit、difficulty、number
分别为调用者支付的交易价格、当前块的汽油上限、当前块的区块难度、当前块的块号、当前块的矿工
timestamp、coinbase
分别为以秒为单位的当前块的时间戳、当前块的矿工
blockhash(b)
指定区块的哈希,只支持最近的256个块