分析編譯器輸出

2022-05-24 10:53 更新

查看編譯器生成的程序集代碼通常很有用。生成的二進(jìn)制文件,即 的輸出,通常難以閱讀。建議使用該標(biāo)志來分析程序集輸出。即使對于大型合同,在更改之前和之后查看程序集的視覺差異通常也非常有啟發(fā)性。solc --bin contract.sol--asm

考慮以下合同(命名,說):contract.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;
contract C {
    function one() public pure returns (uint) {
        return 1;
    }
}

以下為solc --asm contract.sol

======= contract.sol:C =======
EVM assembly:
    /* "contract.sol":0:86  contract C {... */
  mstore(0x40, 0x80)
  callvalue
  dup1
  iszero
  tag_1
  jumpi
  0x00
  dup1
  revert
tag_1:
  pop
  dataSize(sub_0)
  dup1
  dataOffset(sub_0)
  0x00
  codecopy
  0x00
  return
stop

sub_0: assembly {
        /* "contract.sol":0:86  contract C {... */
      mstore(0x40, 0x80)
      callvalue
      dup1
      iszero
      tag_1
      jumpi
      0x00
      dup1
      revert
    tag_1:
      pop
      jumpi(tag_2, lt(calldatasize, 0x04))
      shr(0xe0, calldataload(0x00))
      dup1
      0x901717d1
      eq
      tag_3
      jumpi
    tag_2:
      0x00
      dup1
      revert
        /* "contract.sol":17:84  function one() public pure returns (uint) {... */
    tag_3:
      tag_4
      tag_5
      jump  // in
    tag_4:
      mload(0x40)
      tag_6
      swap2
      swap1
      tag_7
      jump  // in
    tag_6:
      mload(0x40)
      dup1
      swap2
      sub
      swap1
      return
    tag_5:
        /* "contract.sol":53:57  uint */
      0x00
        /* "contract.sol":76:77  1 */
      0x01
        /* "contract.sol":69:77  return 1 */
      swap1
      pop
        /* "contract.sol":17:84  function one() public pure returns (uint) {... */
      swap1
      jump  // out
        /* "#utility.yul":7:125   */
    tag_10:
        /* "#utility.yul":94:118   */
      tag_12
        /* "#utility.yul":112:117   */
      dup2
        /* "#utility.yul":94:118   */
      tag_13
      jump  // in
    tag_12:
        /* "#utility.yul":89:92   */
      dup3
        /* "#utility.yul":82:119   */
      mstore
        /* "#utility.yul":72:125   */
      pop
      pop
      jump  // out
        /* "#utility.yul":131:353   */
    tag_7:
      0x00
        /* "#utility.yul":262:264   */
      0x20
        /* "#utility.yul":251:260   */
      dup3
        /* "#utility.yul":247:265   */
      add
        /* "#utility.yul":239:265   */
      swap1
      pop
        /* "#utility.yul":275:346   */
      tag_15
        /* "#utility.yul":343:344   */
      0x00
        /* "#utility.yul":332:341   */
      dup4
        /* "#utility.yul":328:345   */
      add
        /* "#utility.yul":319:325   */
      dup5
        /* "#utility.yul":275:346   */
      tag_10
      jump  // in
    tag_15:
        /* "#utility.yul":229:353   */
      swap3
      swap2
      pop
      pop
      jump  // out
        /* "#utility.yul":359:436   */
    tag_13:
      0x00
        /* "#utility.yul":425:430   */
      dup2
        /* "#utility.yul":414:430   */
      swap1
      pop
        /* "#utility.yul":404:436   */
      swap2
      swap1
      pop
      jump  // out

    auxdata: 0xa2646970667358221220a5874f19737ddd4c5d77ace1619e5160c67b3d4bedac75fce908fed32d98899864736f6c637827302e382e342d646576656c6f702e323032312e332e33302b636f6d6d69742e65613065363933380058
}

或者,上述輸出也可以在編譯合約后從Remix的“編譯詳細(xì)信息”選項下獲得。

請注意,輸出從創(chuàng)建/構(gòu)造函數(shù)代碼開始。部署代碼作為子對象的一部分提供(在上面的示例中,它是子對象的一部分)。該字段對應(yīng)于合同元數(shù)據(jù)。程序集輸出中的注釋指向源位置。請注意,這是一個內(nèi)部生成的實用程序函數(shù)文件,可以使用標(biāo)志獲取該文件。asmsub_0auxdata#utility.yul--combined-json generated-sources,generated-sources-runtime

同樣,可以使用以下命令:獲得優(yōu)化的程序集。通常,有趣的是,Solidity中的兩個不同源是否會產(chǎn)生相同的優(yōu)化代碼。例如,要查看表達(dá)式 ,是否生成相同的字節(jié)碼。這可以通過獲取相應(yīng)的程序集輸出來輕松完成,之后可能會剝離引用源位置的注釋。solc --optimize --asm contract.sol(a * b) / ca * b / cdiff

注意

輸出未設(shè)計為機(jī)器可讀。因此,在 solc 的次要版本之間,輸出可能會發(fā)生重大更改。--asm


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號