【Solidity Yul Assembly】2.1 | Memory Operations

  • 0xE
  • 更新于 2024-08-21 16:05
  • 阅读 634

从本章开始,我们来研究内存布局。

在你做以下操作时将使用到内存:

  1. 外部调用合约的时候,返回值将放在内存中。
  2. 设置外部调用函数的参数。
  3. revert 时返回错误信息。
  4. 日志信息。
  5. 创建其他智能合约。
  6. 使用 keccak256 函数。

概述

  • 内存相当于其他语言的“堆”
    • 但是没有垃圾回收机制与 free 命令。
    • 内存以 32 字节序列的形式布局。以 32 字节的增量来寻址。
    • [0x00 - 0x20) [0x20 - 0x40) [0x40 - 0x60) [0x60 - 0x80) [0x80 - 0x100)...
  • 只有 4 条指令与内存有关
    • mload, mstore, mstore8, msize
  • 用纯 yul 写的代码,内存比较容易使用。但在 solidity/yul 的混合代码中, solidity 使用了特殊的方式来使用内存。
  • 重要的是,每次内存访问都会消耗 gas,且访问距离越远,消耗的 gas 越多。
    • mload(0xffffffffffffffff) 指令将会超出 3000万 gas 使用的限制。
    • 因此,像在存储中通过哈希值定位位置的方法在内存中不可行。
  • mstore(p, v) 将值 v 存储到内存地址 p 开始的“内存槽”中(以后文章中“内存槽”指的是从该地址开始的 32 字节区域)。
  • mload(p) 是从内存槽 p[p..0x20] 中获取 32 字节的数据。
  • mstore8(p, v) 仅将 1 字节的数据存储到地址 p 中。
  • msize() 返回当前事务中最大的可访问内存索引。

图解内存

比如,我想将32字节的 0xff...fff 存储到内存槽 0x00 中,将得到以下的结果,可以看到地址0x00 - 0x19都填了ff1.png 需要注意的是,内存的最小单位是 1 字节,这与存储槽不同。因此,如果将数据存储在内存槽 0x01 中,可以看到地址0x01 - 0x20都填了ff

2.png

如果存储的数据较小,例如 mstore(0x00, 7),首先会将 7 扩展为 32 字节,即 mstore(0x00, 0x000...0007),结果如下:

3.png

而使用 mstore8(0x00, 0x7) 时,则只会在地址 0x00 处存入 1 字节的值:

4.png

总结 今天,我们对内存简单的开个头,下一讲我们将讲解 Solidity 是如何使用内存的。

关于作者 0xE: Twitter Telegram

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,做过FHE,联盟链,现在是智能合约开发者。 刨根问底探链上真相,品味坎坷悟Web3人生。