EVM详解之memory

EVM详解之memory

文章旨在记录过去所学知识,若文章内容存在不当,欢迎指出。若对文章内容感兴趣,也欢迎评论区留言讨论!文章部分图片来自他人博客!

一、memory的结构

EVM中的主要数据存储结构包括Storage、Memeory、Stack、Calldata。本章主要介绍Memory数据结构。Memory可以看作是一个非常长的数组,其最低长度为0,最长长度为2**64字节,而每个存储块都是32字节。其结构如下图所示:
EVM——Memory
**通常Memory的前四个存储块(4×32字节)用作保留空间,用于不同的用途,而不用作一般局部变量的存储。**从0x80开始以后的空间采用做一般局部变量的存储。

  1. 前两个内存块(0x00,0x20)用作哈希对象的临时存储空间:也就是说只有当字节码中出现SHA3字节码时,这两个存储块才会被使用,否则不会被使用,一般来说哈希函数都是以这样的方式在字节码中呈现:SHA3(0,40)。
  2. 第三个内存块(0x40)用作空闲内存指针
  3. 第四个内存块(0x60)作为零位插槽,永久为0。
    在这里插入图片描述

二、memory的特点

EVM内存有4个主要特点:

  • 廉价 = 在Gas方面。
  • 可变 = 可以被覆盖和改变。
  • 相对于交易 = 来自于函数调用,或构造函数 (=合约创建)
  • 短期的 = 不持久的和在外部函数调用之间被删除。
    EVM内存是一个字节寻址的空间。中的所有字节最初都是空的(定义为零)。它是个可变的数据区,意味着你可以从它那里读取和写入。像calldata一样,内存是通过字节索引来寻址的,在内存中一次只能读32字节的字。

EVM的内存也是易失的。存储在内存中的值在外部调用之间不会持续存在。当一个合约调用另一个合约时,会获得一个新的内存实例。内存并没有被擦除和清空。EVM内存的每个新实例都是特定于一个执行环境,即当前的合约执行。因此,我们应该记住,EVM内存是特定于1)消息调用和2)被调用合约的执行环境的。

三、memory的工作方式

memory是用来存储局部变量的。主要存储的有两种数据: 1.复杂类型的函数参数 2.复杂类型的局部变量。solidity中复杂类型主要是指:指的是诸如结构体、数组、bytes和strings等变量。
一旦函数调用结束,这些用关键字memory定义的变量将消失。这就是我们之前所说的 不持久化 的意思。原因是,memory告诉Solidity在运行时为该变量创建一块空间,保证其大小和结构,以便在函数执行过程中将来用于该函数。

3.1空闲内存指针

要想清楚memory的工作方式,首先要清楚memory中的空闲内存指针。空闲内存指针存放在memory中的第三个存储块(0x40),它指向下一个存放在memory中的变量应该存放的位置(存储块的序号offset),你可以发现对于任何一段合约字节码,都是以0x6080604052开始,它代表的含义是:
在这里插入图片描述
现在我们一步步对其进行解释,第一个push操作将80推入栈中,第二个push将40推入栈中,Mstore()从栈中弹出两个操作数,由于栈的先进后出的特点,所以进行的操作是Mstore(40,80),也就是将0x80存放到memory中0x40的位置,刚才我们介绍了0x40是空闲内存指针,他其中存放的值即为下一个要存放进memory中的值存放的位置,所以如果EVM要存放下一个值进memory就应该存放在0x80的位置。(为什么第一个就存放在0x80的位置呢,因为刚才已经介绍过了memory的前四个存储块用作特殊用途!)

而且EVM规定,在每次使用空闲内存指针存储的数之前,都会先更新其中的值,拿下面的合约函数为例:
在这里插入图片描述
在执行完212号指令之后,test变量的信息已经被全部存放到memory中了,string类型有两个信息会被存放在memory中,一是字符串长度0x13,二是字符串本身:

1.存储字符串长度19=0x13

在这里插入图片描述

2.更新空闲内存指针
在这里插入图片描述
进行完这一步之后,空闲内存指针的值被更新为100。

3.存储字符串本身
在这里插入图片描述

3.2了解MSTORE、MSTORE8、MLOAD操作码

MSTORE、MSTORE8、MLOAD这三个操作码,对memory的工作至关重要。

1.MSTORE(arg0,arg1):该操作码的作用是从栈顶弹出两个元素,第一个为arg0,第二个为arg1,将arg1作为值存放到memory以arg0为序号的内存块。下面的图片描述了MSTORE的工作流程。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.MLOAD(arg):该操作码的作用是从栈顶弹出一个元素作为arg,然后从memory中存储块为arg的位置取出其中的值返回栈中。下面的图片描述了MLOAD的工作流程。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.MSTORE8(arg0,arg1):该操作码的作用和MSTORE操作码几乎一样,只是MSTORE操作码的存储的值以32字节为单位,即使你的值没有32字节,EVM也会自动为你填充至32字节。而MSTORE8操作码存储的值以1字节为单位。其他工作原理都一样。并且一般来说只有在代码中使用了汇编去指定,字节码中才会出现MSTORE8,否则都是MSTORE。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值