【问题标题】:How are Ethereum bytecode JUMPs and JUMPDESTs resolved?以太坊字节码 JUMP 和 JUMPDEST 是如何解决的?
【发布时间】:2017-11-27 21:57:46
【问题描述】:

我一直在寻找有关以太坊如何处理跳转和跳转目的地的信息。从各种博客和黄皮书我发现如下:

JUMP 采用的操作数和JUMPI 采用的两个操作数中的第一个是PC 设置的值(假设第一个堆栈值!在JUMPI 的情况下为0) .

但是,查看this 合约的创建代码(作为操作码),前几个操作码/值是:

PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0x00f8 JUMPI

据我了解,这意味着如果ISZERO != 0 推入堆栈的值,则PC 将更改为0x00f8,因为JUMPI 从堆栈中取出两个,检查第二个是否为 0如果不是,则将 PC 设置为其第一个操作数的值。

我遇到的问题是十进制的0x00f8 是248。合约中的第 248 个位置似乎是MSTORE 而不是JUMPDEST,这将导致合约无法执行,因为JUMP* 只能指向有效的JUMPDEST。

大概合同不会故意跳转到无效的目的地?

如果有人能解释如何解决跳转和跳转目的地,我将不胜感激。

【问题讨论】:

    标签: bytecode ethereum smartcontracts evm


    【解决方案1】:

    如果对他人有帮助:

    EVM 逐字节读取而不是逐字读取引起了混淆。

    从问题的示例中,0x00f8 将是第 248 个字节,而不是第 248 个字。

    由于每个操作码都是 1 字节长,PC 在读取操作码时通常会加 1。

    但是,在PUSH 指令的情况下,还包括有关将以下多少字节作为其操作数的信息。

    例如,PUSH2 占用后面的 2 个字节,PUSH6 占用后面的 6 个字节,依此类推。这里PC 会为PUSH 增加1,然后对于PUSH 使用的数据的每个字节分别增加2 或6。

    【讨论】:

      【解决方案2】:

      只想指出JUMP和JUMPI是有区别的。

      JUMP 只从堆栈中获取 1 个元素,即目标。这通常是推送到堆栈的十六进制偏移量。

      JUMPI 是一个条件跳转,它从堆栈中获取顶部 2 个元素,即目标和条件。

      在您给出的示例中,条件是 ISZERO(检查堆栈的最顶部元素是否为 0)。
      因此,如果返回 true,它将跳转到偏移量 0x00f8(十进制为 248)的目标。

      如果条件为假,程序计数器只会加1。

      在您提到的合同中,它是(程序计数器)248 处的 JUMPDEST 操作码。

      程序计数器取决于操作码。操作码将多少字节推入堆栈等。例如

      PUSH1 0x60  - PC[0]
      PUSH1 0x40  - PC[2]
      MSTORE      - PC[4]
      CALLDATASIZE- PC[5]
      ISZERO      - PC[6]
      PUSH2 0x00f8- PC[7]
      JUMPI       - PC[10]
      

      也许这个网站会让你对操作码有更好的了解https://ethervm.io/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-21
        • 2018-12-26
        • 2022-11-16
        • 1970-01-01
        • 2018-07-14
        • 2018-06-11
        • 2016-02-28
        • 1970-01-01
        相关资源
        最近更新 更多