共计 982 个字符,预计需要花费 3 分钟才能阅读完成。
在某些状况下,咱们心愿在 solidity 中结构一个 buffer,首先咱们应该为这个 buffer 分配内存。在 solidity 中,只有 bytes 这样的构造给咱们用,然而当初切片和替换对应地位的数据的操作在 bytes 上不容易实现。咱们只好借助于 assembly 来实现,首先就是为 buffer 分配内存。
间接上代码:
struct buffer {
bytes buf;
uint capacity;
}
function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {if (capacity % 32 != 0) {capacity += 32 - (capacity % 32);
}
// Allocate space for the buffer data
buf.capacity = capacity;
assembly {let ptr := mload(0x40)
mstore(buf, ptr)
mstore(ptr, 0)
mstore(0x40, add(32, add(ptr, capacity)))
}
return buf;
}
咱们先定义了一个构造体 buffer,蕴含其内容 buf 和总容量 capacity
再定义一个 init 办法 (其实 buffer 是传入的,也能够用来 resize).
以太坊保在 0x40 地址保留了下一个可用的指针(free pointer)。
let ptr := mlod(0x40)
留神函数第一个参数buffer memory buf
, 有个 memory 关键字,阐明 buf 也是在内存中的,buf 是指针的别名,其值是 buf 对象寄存的地址。
mstore(buf, ptr)
把可用的指针的地址替换了 buf 的地址
mstore(ptr ,0)
是把 ptr 地址的指向的数据变成 0,也就是说把 buf 初始化成 0,因为 EVM 不保障 0x40 地址中的指针指向的是全 0 数据
mstore(0x40, add(32, add(ptr, capacity)))
这行的作用是更新 0x40 的地址,指向下一个可用的指针。EVM 不会解决 0x40 的更新,用户必须要本人解决。如何更新 0x40 的值呢?咱们能够跳过刚刚开辟出来的 buffer,把接下来的地址赋到 0x40 上。刚刚开拓的空间是 capacity 大小,再加上前 32 位(0x20)是数据的长度,所以 0x40 要在 ptr 的根底上偏移
capacity + 32