首页 > 解决方案 > solc 的 --opcodes 和 --asm 有什么区别?

问题描述

我正在学习低级 Solidity 内联汇编,但对不同的输出格式感到困惑。

Solidity 编译器的输出选项说:

  --asm                EVM assembly of the contracts.
  --opcodes            Opcodes of the contracts.

我尝试了两种选择来编译下面的合同:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract MyContract {
    string bar = "Hello World";

    function foo() public view returns(string memory) {
        return bar;
    }
}

该命令solc -o output --asm contract.sol生成 MyContract.evm:

    /* "contract.sol":70:208  contract MyContract {... */
  mstore(0x40, 0x80)
    /* "contract.sol":96:122  string bar = "Hello World" */
  mload(0x40)
  dup1
  0x40
  add
  0x40
  mstore
  dup1
  0x0b
  dup2
  mstore
  0x20
  add
  0x7657399374655890603765000000000000000000000000000000000000000000
  dup2
  mstore
  pop
  0x00
  swap1
  dup1
  mload
  swap1
  0x20
  add
  swap1
  tag_1
  swap3
  swap2
  swap1
  tag_2
  jump  // in
tag_1:
  pop
    /* "contract.sol":70:208  contract MyContract {... */
  callvalue
  dup1
... (and a lot more code)

该命令solc -o output --opcodes contract.sol生成 MyContract.opcode:

PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0xB DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7657399374655890603765000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x0 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH2 0x4F SWAP3 SWAP2 SWAP1 PUSH2 0x62 JUMP JUMPDEST POP CALLVALUE DUP1 ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x166 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH2 0x6E SWAP1 PUSH2 0x105 JUMP JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH2 0x90 JUMPI PUSH1 0x0 DUP6 SSTORE PUSH2 0xD7 JUMP JUMPDEST DUP3 PUSH1 0x1F LT PUSH2 0xA9 JUMPI DUP1 MLOAD PUSH1 ... ...

它们看起来非常相似,虽然不是 100% 相互匹配......

问题

  1. 与输出相比,是否--opcodes只是提供更紧凑的汇编代码形式--asm
  2. PUSH1 0x80 PUSH1 0x40 MSTORE--opcodes格式 与格式mstore(0x40, 0x80)--asm他们在做同样的事情吗?(我猜是这样,但不是 100% 肯定......)
  3. 有没有办法以--opcodes漂亮的格式而不是单行打印?
  4. 有没有什么好的资源来学习 Solidity 内联汇编?我四处搜索,但发现了一堆单页博客,它们很好地解释了基础知识,但不幸的是,它们都没有提供完整而深入的教程

标签: ethereum

解决方案


1.与输出--opcodes相比,是否只是提供更紧凑的汇编代码形式--asm

这有点正确。您仍然可以将程序集转换为操作码并获得相同的结果。

汇编代表一组“低级”指令。操作码是传递给 EVM 的“真实”二进制指令。例如,请参见将操作码转换为二进制的此表

2.格式PUSH1 0x80 PUSH1 0x40 MSTORE与格式。他们在做同样的事情吗?(我猜是这样,但不是 100% 肯定......)--opcodesmstore(0x40, 0x80)--asm

是的,他们正在做同样的事情 - 请参阅 1 的答案。当您在 Solidity 中运行此代码段时

assembly {
    mstore(0x40, 0x80)
}

你得到相同的操作码。

混音调试器

3. 有没有办法以--opcodes漂亮的格式打印而不是单行打印?

您可以tr在任何其他文本格式的 unix cli 命令上使用。

echo "PUSH1 0x80 PUSH1" | tr ' ' '\n'
PUSH1
0x80
PUSH1

有关更多方法,请参阅此论坛帖子

4、有没有什么好的学习Solidity内联汇编的资源?

除了文档,我什么都不知道,所以我会让其他人给出更好的答案。但是 Solidity 仍然是一项相当新的技术,所以我的猜测是,大多数专门从事 Solidity 组装的人都是通过反复试验学习的。


推荐阅读