本文深入探讨了操作码(Opcodes)这一计算机处理器和虚拟机中的基本指令,从传统CPU到以太坊虚拟机(EVM)等区块链环境。文章详细介绍了Opcodes的机制、工具和实际应用,重点关注EVM合约Opcodes,并结合实例分析了如何在经典计算和前沿区块链生态系统中运用Opcodes,以及它们在操作系统、嵌入式系统、区块链、安全和编译器等领域的关键作用。
Opcodes,或称操作码,是驱动每个计算机处理器和虚拟机运行的基本指令,从传统的 CPU 到以太坊虚拟机 (EVM) 这样的区块链环境。这些紧凑的二进制或十六进制代码指定精确的操作——算术、数据移动或程序流程——构成人类编写的代码和机器执行之间的桥梁。理解操作码可以更深入地了解底层编程、性能优化和现代区块链技术。本文提供了对操作码的全面、独特的探索,将操作码的机制、工具和实际应用与对 EVM 合约操作码的特别关注相结合。通过实践的例子,我们将揭示截至 2025 年 4 月 30 日的操作码的复杂性,使你掌握在经典计算和前沿区块链生态系统中航行的知识。
操作码是一种机器可读的代码,它指示处理器或虚拟机执行特定的操作。作为处理器指令集架构 (ISA) 的一部分,操作码通常与操作数配对——数据、寄存器或内存地址——以完成指令。例如,在 x86 架构中,操作码 0xB8
表示将值加载到寄存器的 MOV
指令,而在 EVM 中,0x01
表示堆栈值的 ADD
操作。
操作码是最低级别的指令,由硬件或虚拟机直接执行。它们因架构(x86、ARM、RISC-V、EVM)而异,反映了每个系统的设计理念和操作约束。
机器代码中的指令包括:
ADD
,JMP
)。5
、EAX
、内存地址 0xA1
)。考虑一个简单的机器代码序列:
901
:输入一个值(操作码 9
,操作数 01
)。306
:将值存储在内存地址 06
中(操作码 3
,操作数 06
)。5A1
:将地址 A1
中的值加载到累加器中(操作码 5
,操作数 A1
)。十六进制因其简洁性而受到青睐——十进制 250 在二进制中是 11111010
,但在十六进制中是 FA
,从而简化了底层编程。
x86 指令 MOV EAX, 5
转换为:
B8 05 00 00 00
。B8
(MOV to EAX).05 00 00 00
(value 5, little-endian).在 EVM 中,ADD
( 0x01
) 弹出两个堆栈值,将它们相加,然后推送结果,指令本身没有显式的操作数。
直接用操作码进行编码很容易出错,因此汇编语言使用助记符——人类可读的缩写——来表示操作码和操作数。例如,机器代码 0001 0100 0011
(add 4 and 3) 在汇编中变为 ADD 4, 3
,其中 ADD
表示操作码 0001
。
助记符是特定于架构的:
ADD EAX, EBX
将 EBX 添加到 EAX。ADD R0, R1, #3
将 3 添加到 R1,存储在 R0 中。ADD
添加顶部的两个堆栈值。汇编简化了底层编程,但需要了解目标 ISA。
在 EVM 汇编中:
PUSH1 0x05 ; Opcode: 60, Operand: 05 (Push 5)
PUSH1 0x03 ; Opcode: 60, Operand: 03 (Push 3)
ADD ; Opcode: 01 (Add 5 + 3)
这会在堆栈上产生 8,操作码为 60 05 60 03 01
。
汇编器将汇编助记符转换为机器代码操作码。 例如,ADD 4, 3
变为 0001 0100 0011
。 反汇编器 反转此操作,将机器代码转换回汇编以进行分析。
section .text
global _start
_start:
mov eax, 5 ; Move 5 into EAX
add eax, 3 ; Add 3 to EAX
mov ebx, eax ; Move EAX to EBX
mov eax, 1 ; Exit system call
int 0x80 ; Call kernel
汇编:
nasm -f elf32 add.asm -o add.o
ld -m elf_i386 add.o -o add
反汇编:
objdump -d add
输出:
08048060 <_start>:
8048060: b8 05 00 00 00 mov $0x5,%eax
8048065: 83 c0 03 add $0x3,%eax
8048068: 89 c3 mov %eax,%ebx
804806a: b8 01 00 00 00 mov $0x1,%eax
804806f: cd 80 int $0x80
操作码包括 b8
(MOV), 83
(ADD), 和 cd
(INT)。
指令格式因架构而异:
在 EVM 中,大多数操作码为 1 字节,操作数(例如,对于 PUSH1
)增加 1-32 字节。 例如,PUSH1 0x03
是 60 03
(2 个字节)。
ADD
( 01
) 是 1 字节,基于堆栈。ADD EAX, 3
( 83 C0 03
) 是 3 字节,基于寄存器。指令周期包括:
对于 ADD 4, 3
:
0001 0100 0011
.0001
(ADD), operands 0100
(4), 0011
(3).流水线 重叠多个指令的这些阶段,从而提高吞吐量。 在 EVM 中,gas 成本会激励最小化周期,因为每个操作码都会消耗 gas(例如,ADD
花费 3 gas)。
架构决定了操作码设计:
0x00 STOP
:停止执行 (0 gas)。0x01 ADD
:将两个堆栈值相加 (3 gas)。0x55 SSTORE
:在存储中存储一个值(如果为新值,则为 20,000 gas)。0x60 PUSH1
:推送一个 1 字节的值 (3 gas)。以太坊中的智能合约依赖 EVM 操作码来执行。 下面是一个简单的 Solidity 合约、其编译的 EVM 操作码以及关键操作的说明的示例。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 public storedValue;
function set(uint256 value) public {
storedValue = value;
}
function get() public view returns (uint256) {
return storedValue;
}
}
使用 Solidity 编译器(例如,通过 Remix),set
函数编译为如下操作码:
PUSH1 0x00 ; Push storage slot 0
CALLDATALOAD ; Load input data (value)
SSTORE ; Store value in storage
机器代码 (hex):
60 00 35 55
60 00
, 3 gas):0
(存储 storedValue
的位置)推送到堆栈上。2. CALLDATALOAD ( 35
, 3 gas):
value
参数)。3. SSTORE ( 55
, 如果是新值,则为 20,000 gas ,如果是更新,则为 5,000 gas):
storedValue
。get
函数可能会编译为:
PUSH1 0x00 ; Push storage slot 0
SLOAD ; Load value from storage
PUSH1 0x00 ; Push return offset
MSTORE ; Store value in memory
PUSH1 0x20 ; Push return size (32 bytes)
PUSH1 0x00 ; Push return offset
RETURN ; Return the value
机器代码:
60 00 54 60 00 52 60 20 60 00 F3
54
, 800 gas): 从存储中检索 storedValue
。52
, 3 gas): 在内存中存储该值以供返回。F3
, 0 gas): 将该值输出给调用者。这个例子突出了 EVM 基于堆栈的、gas 驱动的执行,其中存储操作 ( SSTORE
, SLOAD
) 成本很高,鼓励优化。
Opcodes 是以下内容的组成部分:
在以太坊中,opcodes 决定了智能合约的行为。 优化低 gas 使用量(例如,最小化 SSTORE
)可降低交易成本。 像 ethervm.io 和 evm.codes 这样的工具提供 opcode 参考和交互式环境。
ADD
、PUSH1
)而不是存储。opcodes 正在发展:
关注英特尔/ARM 博客、以太坊改进提案 (EIP) 以及 Hot Chips 等活动以获取更新。
Opcodes 是计算的脉搏,驱动着从传统 CPU 到区块链虚拟机的一切。通过掌握 opcodes——通过汇编、像 NASM 和 Remix 这样的工具以及像 evm.codes 这样的资源——你将深入了解软件执行的机制。无论是优化以太坊智能合约、调试嵌入式系统还是探索 AI 硬件,opcodes 都提供了一个了解技术核心的窗口。拥抱挑战,尝试提供的示例,并在 2025 年及以后释放底层编程的力量。
- 原文链接: medium.com/@ankitacode11...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!