第18节:assembly汇编
小白入门:https://github.com/dukedaily/solidity-expert ,欢迎star转发,文末加V入群。
职场进阶: https://dukeweb3.com
汇编语言为我们编写合约提供了更大的灵活度,solidity是建立在汇编之上的高级语言,方便开发:
- 汇编在写库的时候很实用,提供更加细颗粒度的编写
- 汇编语言为Yul语法
- 使用assembly { ... }包裹
节约gas
测试:input: [1,2,3]
- 23374 gas -> sumSolidity(最低效)
- 23082 gas -> sumAsm(次之)
- 22895 gas -> sumPureAsm(最高效)
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
library VectorSum {
// This function is less efficient because the optimizer currently fails to
// remove the bounds checks in array access.
function sumSolidity(uint[] memory data) public pure returns (uint sum) {
for (uint i = 0; i < data.length; ++i)
sum += data[i];
}
// We know that we only access the array in bounds, so we can avoid the check.
// 0x20 needs to be added to an array because the first slot contains the
// array length.
function sumAsm(uint[] memory data) public pure returns (uint sum) {
for (uint i = 0; i < data.length; ++i) {
assembly {
sum := add(sum, mload(add(add(data, 0x20), mul(i, 0x20))))
}
}
}
// Same as above, but accomplish the entire code within inline assembly.
function sumPureAsm(uint[] memory data) public pure returns (uint sum) {
assembly {
// Load the length (first 32 bytes)
let len := mload(data)
// Skip over the length field.
//
// Keep temporary variable so it can be incremented in place.
//
// NOTE: incrementing data would result in an unusable
// data variable after this assembly block
let dataElementLocation := add(data, 0x20)
// Iterate until the bound is not met.
for
{ let end := add(dataElementLocation, mul(len, 0x20)) }
lt(dataElementLocation, end)
{ dataElementLocation := add(dataElementLocation, 0x20) }
{
sum := add(sum, mload(dataElementLocation))
}
}
}
}