深入了解EVM #1:EVM字节码与环境

  • jpmorais
  • 发布于 2023-04-18 13:10
  • 阅读 68

本文深入探讨了以太坊虚拟机(EVM)及其字节码的工作原理。文章介绍了虚拟机的基本概念、字节码结构、操作码以及EVM的执行环境,包括内存、栈、调用数据和存储的功能与特点,为理解EVM的运作提供了基础知识。

以太坊及其他区块链实现了一种名为 Ethereum Virtual Machine 的虚拟机,简称 EVM。为了理解虚拟机是什么,让我们简单了解一下计算机是如何工作的。你现在使用的计算机,无论是桌面电脑、笔记本电脑、智能手机(或者将来可能是一台冰箱),都有一个中央处理单元 CPU,能够执行一些预定义的操作。这些操作必须通过位来指示给 CPU。这就是我们说 CPU 理解机器码的原因。

与机器语言最接近的语言是 Assembly。在 Assembly 中,我们可以直接与 CPU 的基本组件(如寄存器)进行交互。此外,我们可以直接与内存进行交互,而在某些语言中这并不总是可行。所谓的 高级语言 通常会为程序员抽象出内存的使用。这使得语言的使用更安全,但也削弱了程序员的一些能力。

虚拟机 是 CPU 的一种模拟。它也有预定义的操作,但这些操作必须被虚拟机理解,而不是 CPU。虚拟机最终是一个能够解释特定语言的程序,它将这种语言(间接)转换为机器语言,并执行需要在 CPU 上执行的内容。

虚拟机理解的语言称为 字节码。每种虚拟机都有自己的字节码及其定义。当我们在 Solidity 或 Vyper 中编写智能合约时,结果必须被转换(编译)为字节码。EVM 字节码并不是机器语言;尽管它看起来是一组位,但它仅仅是一种表示。

当我们使用 solc 编译器将 Solidity 转换为字节码时,结果是以 UTF-8 编码的十六进制数。如果你曾见过由 solc 编译的字节码,它看起来像 0x6080 ……其中 0x 表示一个十六进制数,而 60(说是六零)是一个十六进制数。它不是字节 0x60,它相当于 ` 字符,而不是数字 60。

因此,字节码是一系列指令,EVM 将解释并执行这些指令。理解字节码比你想象的要简单。它由一组必须按顺序从左到右执行的字节组成。这组字节可以分为 操作符操作数。一些操作符有操作数,但并非所有。操作符被称为 OPCODES

让我们分析一个简单的字节码:0x6001600201。首先,我们将其拆分为一组字节。

60 01 60 02 01

每个字节可以是一个操作符、一个完整的操作数或操作数的一部分,因为操作数可以不止 1 个字节。操作符由一个字节表示。

字节 60PUSH1 操作码,它将一个字节添加到堆栈中。我们很快就会看到什么是堆栈。现在,我的意图只是让你能读懂字节码。PUSH1 操作码是一个期望 1 字节操作数的操作符,接下来的字节。因此,完整的语句是 60 01

翻译成自然语言意味着将值 01 放到堆栈中。下一个语句非常相似。

60 02

这条指令的意思是:将值 02 放到堆栈中。只剩下 1 个字节 01,它是一个操作符。它对应于 ADD 操作码,该操作码将堆栈上的值(1 和 2)相加,并将结果返回到堆栈。我们的字节码的最终结果将在堆栈上是数字 3。

注意字节 01 同时作为操作数和操作符使用。然而,根据它的使用上下文,容易找出它所代表的含义。

现在我们了解了如何阅读字节码的一些内容,接下来看看 EVM 的工作环境。

EVM 环境

EVM 在一个维持 4 个位置以访问和/或存储信息的环境中工作,分别是 内存堆栈调用数据存储

内存

内存的工作方式类似于计算机的内存,更具体地说,是 RAM(随机存取内存)。RAM 的概念是信息可以在特定位置被读取和存储,而不仅仅是顺序地存储。也就是说,我们可以在特定的内存地址上存储数据。

字节码在 EVM 中执行的环境是一个虚拟环境,因此就好像我们拥有一个完整的内存,从地址 0x00 开始。EVM 通常以 32 字节的包进行操作。由于 32 以十六进制表示为 0x20,我们将在内存中按以下顺序指示地址:0x000x200x400x60 …… 我们可以在这些地址读取和写入信息。

堆栈

堆栈字面上是一个按照 LIFO(后进先出)原则工作的数据堆。这意味着添加到堆栈中的数据位于顶部,而从堆栈中移除的数据也是从堆栈顶部移除的。让我们在之前的例子中表示堆栈。当字节码开始执行时,堆栈是空的。指令 60 01 将字节 01 放在堆栈的顶部。然后,指令 60 02 将字节 02 放在堆栈顶部,推开字节 01。最后,指令 01 移除堆栈中的两个值,并将它们的和的结果放在堆栈的顶部。

堆栈上过程的示意图。

调用数据

调用数据是存储调用或交易有效负载信息的地方。调用负载通常是要执行的函数的签名,然后是函数参数的 ABI 编码。但是,原则上,调用数据可以是任何内容。EVM 不能写入调用数据,属于只读位置。

存储

存储是一个永久存储空间。每个合约账户都有自己的存储,而账户只能访问自己的存储。不可能直接访问另一个账户的存储。我们可以将存储视为一个私人数据库,其中数据以键值形式存储。在存储中存储信息的成本是比较高的,因而我们必须优化存储的使用。

在接下来的课程中,我们将详细讨论存储结构。

总结

总之,EVM 执行一种称为字节码的语言,这种执行发生在一个由堆栈、内存、调用数据和存储组成的环境中。在接下来的课程中,我们将进一步了解 EVM 的操作符和操作数、其内部结构以及操作码、Solidity 和 Yul(一种更低级的语言,称为 EVM Assembly)之间的关系。

感谢你的阅读!

欢迎对本文提出意见和建议。

任何贡献都非常欢迎。www.buymeacoffee.com/jpmorais

  • 原文链接: medium.com/coinmonks/lea...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
jpmorais
jpmorais
江湖只有他的大名,没有他的介绍。