EVM Opcodes 101

1. Hello Opcodes
2. Opcodes分类
3. 堆栈指令
4. 算数指令
5. 比较指令
6. 位级指令
7. 内存指令
8. 存储指令
9. 控制流指令
10. 区块信息指令
11. 堆栈指令2
12. SHA3指令
13. 账户指令
14. 交易指令
15. Log指令
2. Opcodes分类
Opcodes分类

我最近在重新学以太坊opcodes,也写一个“WTF EVM Opcodes极简入门”,供小白们使用。

推特:@0xAA_Science

社区:Discord|微信群|官网 wtf.academy

所有代码和教程开源在github: github.com/WTFAcademy/WTF-Opcodes


这一讲,我们将介绍Opcodes的分类,对Opcodes进行分类,并使用这些操作码来创建一个简单的程序,执行1+1的计算。

Opcodes分类

Opcodes可以根据功能分为以下几类:

  • 堆栈(Stack)指令: 这些指令直接操作EVM堆栈。这包括将元素压入堆栈(如PUSH1)和从堆栈中弹出元素(如POP)。

  • 算术(Arithmetic)指令: 这些指令用于在EVM中执行基本的数学运算,如加法(ADD)、减法(SUB)、乘法(MUL)和除法(DIV)。

  • 比较(Comparison)指令: 这些指令用于比较堆栈顶部的两个元素。例如,大于(GT)和小于(LT)。

  • 位运算(Bitwise)指令: 这些指令用于在位级别上操作数据。例如,按位与(AND)和按位或(OR)。

  • 内存(Memory)指令: 这些指令用于操作EVM的内存。例如,将内存中的数据读取到堆栈(MLOAD)和将堆栈中的数据存储到内存(MSTORE)。

  • 存储(Storage)指令: 这些指令用于操作EVM的账户存储。例如,将存储中的数据读取到堆栈(SLOAD)和将堆栈中的数据保存到存储(SSTORE)。这类指令的gas消耗比内存指令要大。

  • 控制流(Control Flow)指令: 这些指令用于EVM的控制流操作,比如跳转JUMP和跳转目标JUMPDEST。

  • 上下文(Context)指令: 这些指令用于获取交易和区块的上下文信息。例如,获取msg.sender(CALLER)和当前可用的gas(GAS)。

evm.codes

我们在WTF-Opcodes教程的入门部分会使用evm.codes来运行Opcodes程序。

1. Opcode列表

evm.codes提供了完整的Opcodes列表,这对于学习Opcodes非常有用。它包括每个Opcode的编号(例如,ADD的编号是0x01)、名称、gas消耗、堆栈输入和输出以及一个简短的描述。

2. Playground

evm.codes还提供了一个在线的Opcodesplayground,你可以在这里运行Opcodes代码。Playground分为三部分:左上角的编辑器,右上角的执行界面,以及右下角的状态界面,它们分别显示你的代码、代码的执行过程和执行结果。

示例: 1+1

我们现在来用Opcodes编写一个简单的程序,这个程序将在堆栈中计算1+1,并将结果保存到内存中。代码如下:

PUSH1 0x01
PUSH1 0x01
ADD
PUSH0
MSTORE

我们来逐行分析这个程序,同时展示每行指令执行后堆栈和内存的状态:

  1. 第1-2行:PUSH1指令将一个长度为1字节的数据压入堆栈顶部。

    PUSH1 0x01
    // stack: [1]
    PUSH1 0x01
    // stack: [1, 1]
  2. 第3行:ADD指令会弹出堆栈顶部的两个元素,计算它们的和,然后将结果压入堆栈。

    ADD
    // stack: [2]
  3. 第4行: PUSH0指令将0压入堆栈。

    PUSH0
    // stack: [0, 2]
  4. 第5行: MSTORE 属于内存指令,它会弹出堆栈顶的两个数据 [offset, value](偏移量和值),然后将value(长度为32字节)保存到内存索引(偏移量)为offset的位置。

    MSTORE
    // stack: []
    // memory: [0: 2]

你可以在evm.codes中验证执行过程和结果。

总结

这一讲,我们介绍了Opcodes的功能分类,并使用opcodes写了第一个程序,计算1+1。接下来,我们会按分类介绍所有的opcodes。

PreviousNext