什么是Assembly
在编写Solidity代码时,我们可以使用assembly{}
关键字开始编写Yul代码,它是一种简化且扩展了的汇编语言。通过使用assembly,我们可以直接访问堆栈,并优化代码以提高内存效率,从而减少执行交易所需的燃气量。这最终降低了用户的交易成本。
然而,在可读性方面存在一些妥协。许多前端开发人员可以阅读Solidity智能合约并理解正在执行的功能以及如何将其应用到他们的web3查询中。相比之下,汇编可能会让人感到有些困惑,如果你不熟悉低级编程,可能很难理解其逻辑和流程。
操作码列表
操作码 | 描述 |
---|---|
add(x, y) | 将栈中的前两个值相加,并用结果替换它们 |
sub(x, y) | 减法操作 |
mul(x, y) | 乘法操作 |
div(x, y) | 除法操作 |
mod(x, y) | 取模操作 |
lt(x, y) | 小于。如果 x 小于 y,则返回 1 |
gt(x, y) | 大于 |
eq(x, y) | 等于。如果 x 等于 y,则返回 1 |
not(x) | 按位取反 (1010 > 0101) |
and(x, y) | 按位与 (1000 AND 1100 > 1000) |
or(x, y) | 按位或 (1000 AND 1100 > 1100) |
xor(x, y) | 按位异或 (1000 XOR 1100 > 0100) |
byte(n, x) | X 的第 N 个字节 |
keccak256(pos, n) | 本地哈希算法 |
pop(x) | 从栈中弹出 X |
mload(pos) | 加载存储在位置 pos 的内存数据 |
mstore(pos, value) | 在位置 pos 的memory中存储值 value |
sload(pos) | 加载存储在位置 pos 的存储数据 |
sstore(pos, value) | 在位置 pos 的storage中存储值 value |
balance(address) | 以 wei 为单位返回地址的以太币余额 |
call(gas, address, value, in, insize, out, outsize) | 调用外部合约,也可用于发送资金,成功时返回 1 |
delegatecall(gas, address, value, in, insize, out, outsize) | 与上述相同,但由用户而不是合约进行调用 |
revert(p, s) | 撤销事务和任何状态更改 |
return(p, s) | 结束执行并返回数据 |
这里需要注意的是mstore
和sstore
的区别,主要存储的位置的不一致,一种是存储在memory中,另一种是存储在storage中。
使用案例
读写
下面我们通过一个例子展示下如何使用Assembly
把数据存储到storage中,然后通过函数读取的方式读出来。
function testAssembly() public {
//定义一个存储的值方便测试.
uint256 x = 123;
bool res;
//将x存储到storage中。
assembly {
sstore(0, x)
}
//在storage中读取x的值,其中0是pos
assembly {
let readX := sload(0)
//将readX的值存储到memory,pos == 0x80的位置。
mstore(0x80, readX)
}
//将0x80中的值取出来.
assembly {
let v := mload(0x80)
if eq(v, x) {
res := true
}
}
//判断最终取出来的v == x?
assert(res);
}
上诉的例子在实际项目中不太可能出现,只是为了展示读写的过程。
基础运算
function testAssembly() public {
//定义一个存储的值方便测试.
uint256 x = 123;
uint256 r = 345;
//将x存储到storage中。
assembly {
x := add(x, 300)
x := sub(x, 78)
}
//判断最终取出来的r == x?
assert(r == x);
}
Follow我的推进行交流学习:https://twitter.com/nifty12111
TG:@coffiasd
Top comments (0)