Assembler

assembler命令行工具允许您将Ethers ASM Dialect汇编成可部署的EVM bytecode,并将EVM字节码反汇编成人类可读的助记符。

帮助

用法: ethers-asm [ FILENAME ] [ OPTIONS ] 选项 --define KEY=VALUE provide assembler defines --disassemble 反汇编输入字节码 --ignore-warnings 忽略警告 --pic 生成独立位置代码 --target LABEL 输出LABEL字节码 (默认: _) 其他选项 --debug 显示错误的堆栈跟踪 --help 显示此用法并退出 --version 显示此版本并退出

示例输入文件

SimpleStore.asm
; SimpleStore (uint) ; Set the initial value of 42 sstore(0, 42) ; Init code to deploy myContract codecopy(0, $myContract, #myContract) return(0, #myContract) @myContract { ; Non-payable jumpi($error, callvalue) ; Get the Sighash shr({{= 256 - 32 }}, calldataload(0)) ; getValue() dup1 {{= sighash("getValue()") }} jumpi($getValue, eq) ; setValue(uint) dup1 {{= sighash("setValue(uint)") }} jumpi($setValue, eq) ; No matching signature @error: revert(0, 0) @getValue: mstore(0, sload(0)) return (0, 32) @setValue: ; Make sure we have exactly a uint jumpi($error, iszero(eq(calldatasize, 36))) ; Store the value sstore(0, calldataload(4)) return (0, 0) ; There is no *need* for the PUSH32, it just makes ; decompiled code look nicer @checksum[ {{= (defines.checksum ? concat([ Opcode.from("PUSH32"), id(myContract.source) ]): "0x") }} ] }
SimpleStore.bin
0x602a6000556044601160003960446000f334601e5760003560e01c8063209652 0x5514602457806355241077146030575b60006000fd5b60005460005260206000 0xf35b6024361415601e5760043560005560006000f3
Note: 字节码文件语法

一个bin文件可以由多个字节码块组成,每个字节可以选择以0x前缀开头,所有的字节必须为偶数长度(因为字节是必需的,每个字节有2个nibbles)。

所有空白都会被忽略。

汇编例子

汇编器通过汇编阶段的多次遍历,将Ethers ASM Dialect成字节码,每次🏪都接近最终结果。

这允许对字节码的一小部分进行修改和调整,直到字节码稳定。This allows for more compact jump destinations,并允许代码包含更高级的元编程技术。

/home/ethers> ethers-asm SimpleStore.asm 0x602a6000556044601160003960446000f334601e5760003560e01c80632096525514602457806355241077146030575b60006000fd5b60005460005260206000f35b6024361415601e5760043560005560006000f3 # Piping in ASM source code /home/ethers> cat SimpleStore.asm | ethers-asm # 和上面一样 # 设置一个ASM文件检查并添加校验和的定义 /home/ethers> ethers-asm --define checksum SimpleStore.asm 0x602a6000556065601160003960656000f334601e5760003560e01c80632096525514602457806355241077146030575b60006000fd5b60005460005260206000f35b6024361415601e5760043560005560006000f37f10358310d664c9aeb4bf4ce7a10a6a03176bd23194c8ccbd3160a6dac90774d6

选项

--define KEY=VALUE or --define FLAG

这允许键/值对(值是一个字符串)和flags (值是true)传递给汇编程序,这可以在Scripting Blocks中访问,例如{{= defined.someKey }}.

--ignore-warnings

默认情况下,任何警告都将被视为一个错误。This enabled by-passing warnings.

--pic

当程序在汇编的时候,标签通常以绝对字节位置给出,可以跳转到for循环和控制流。这就意味着程序必须安装在特定的位置。

通过指定Position Independent Code flag,代码将以所有偏移量都是相对的方式生成,允许程序在不影响其逻辑的情况下移动。

不过这确实会产生额外的gas成本,即每个偏移量需要8个gas。

--target LABEL

所有程序都有一个名为_ 的作用域,默认情况下是进行汇编的。这个选项允许其他被标记了的目标( 作用域或者数据段(Data Segment)进行汇编 。整个程序仍然按照常规汇编,因此这只影响输出的一部分。

反汇编程序例子

反汇编程序显示给定字节码的偏移量和助记符。这个格式在未来可能会改变,以使人类更易于阅读。

/home/ethers> ethers-asm --disassemble SimpleStore.bin 0000 : 0x2a ; #1 0002 : 0x00 ; #1 0004 : SSTORE 0005 : 0x44 ; #1 0007 : 0x11 ; #1 0009 : 0x00 ; #1 000b : CODECOPY 000c : 0x44 ; #1 000e : 0x00 ; #1 0010 : RETURN 0011 : CALLVALUE 0012 : 0x1e ; #1 0014 : JUMPI 0015 : 0x00 ; #1 0017 : CALLDATALOAD 0018 : 0xe0 ; #1 001a : SHR 001b : DUP1 001c : 0x20965255 ; #4 0021 : EQ 0022 : 0x24 ; #1 0024 : JUMPI 0025 : DUP1 0026 : 0x55241077 ; #4 002b : EQ 002c : 0x30 ; #1 002e : JUMPI 002f*: JUMPDEST 0030 : 0x00 ; #1 0032 : 0x00 ; #1 0034 : REVERT 0035*: JUMPDEST 0036 : 0x00 ; #1 0038 : SLOAD 0039 : 0x00 ; #1 003b : MSTORE 003c : 0x20 ; #1 003e : 0x00 ; #1 0040 : RETURN 0041*: JUMPDEST 0042 : 0x24 ; #1 0044 : CALLDATASIZE 0045 : EQ 0046 : ISZERO 0047 : 0x1e ; #1 0049 : JUMPI 004a : 0x04 ; #1 004c : CALLDATALOAD 004d : 0x00 ; #1 004f : SSTORE 0050 : 0x00 ; #1 0052 : 0x00 ; #1 0054 : RETURN /home/ethers> cat SimpleStore.bin | ethers-asm --disassemble # 和上面一样