ethers.js/docs.wrm/cli/asm.wrm
2020-11-22 23:03:50 -05:00

221 lines
7.4 KiB
Plaintext

_section: Assembler @<cli-asm>
The assembler Command-Line utility allows you to assemble the
[Ethers ASM Dialect](asm-dialect) into deployable EVM bytecode
and disassemble EVM bytecode into human-readable mnemonics.
_subsection: Help
_code: @lang<text>
Usage:
ethers-asm [ FILENAME ] [ OPTIONS ]
OPTIONS
--define KEY=VALUE provide assembler defines
--disassemble Disassemble input bytecode
--ignore-warnings Ignore warnings
--pic generate position independent code
--target LABEL output LABEL bytecode (default: _)
OTHER OPTIONS
--debug Show stack traces for errors
--help Show this usage and exit
--version Show this version and exit
_subsection: Example Input Files
_code: SimpleStore.asm @lang<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")
}}
]
}
_code: SimpleStore.bin @lang<text>
0x602a6000556044601160003960446000f334601e5760003560e01c8063209652
0x5514602457806355241077146030575b60006000fd5b60005460005260206000
0xf35b6024361415601e5760043560005560006000f3
_note: Note: Bytecode File Syntax
A bin file may be made up of multiple blocks of bytecode, each may
optionally begin with a ``0x`` prefix, all of which **must** be of
even length (since bytes are required, with 2 nibbles per byte)
All whitespace is ignored.
_subsection: Assembler Examples
The assembler converts an [Ethers ASM Dialect](asm-dialect) into
bytecode by running multiple passes of an assemble stage, each pass
more closely approximating the final result.
This allows small portions of the bytecode to be massaged and tweaked
until the bytecode stabilizes. This allows for more compact jump
destinations and for code to include more advanced meta-programming
techniques.
_code: @lang<shell>
/home/ethers> ethers-asm SimpleStore.asm
0x602a6000556044601160003960446000f334601e5760003560e01c80632096525514602457806355241077146030575b60006000fd5b60005460005260206000f35b6024361415601e5760043560005560006000f3
# Piping in ASM source code
/home/ethers> cat SimpleStore.asm | ethers-asm
# Same as above
# Setting a define which the ASM file checks and adds a checksum
/home/ethers> ethers-asm --define checksum SimpleStore.asm
0x602a6000556065601160003960656000f334601e5760003560e01c80632096525514602457806355241077146030575b60006000fd5b60005460005260206000f35b6024361415601e5760043560005560006000f37f10358310d664c9aeb4bf4ce7a10a6a03176bd23194c8ccbd3160a6dac90774d6
_heading: Options
_definition: **-\-define KEY=VALUE** //or// **-\-define FLAG**
This allows key/value pairs (where the value is a string) and
flags (which the value is ``true``) to be passed along to the
assembler, which can be accessed in
[Scripting Blocks](asm-dialect-scripting), such as ``{{= defined.someKey }}``.
_definition: **-\-ignore-warnings**
By default any warning will be treated like an error. This enabled
by-passing warnings.
_definition: **-\-pic**
When a program is assembled, the labels are usually given as an
absolute byte position, which can be jumped to for loops and
control flow. This means that a program must be installed at a specific
location.
Byt specifying the **Position Independent Code** flag, code
will be generated in a way such that all offsets are relative, allowing
the program to be moved without any impact to its logic.
This does incur an additional gas cost of 8 gas per offset access though.
_definition: **-\-target LABEL**
All programs have a root scope named ``_`` which is by default
assembled. This option allows another labelled target (either a
[[asm-dialect-scope]] or a [[asm-dialect-datasegment]] to be
assembled instead. The entire program is still assembled per usual,
so this only impacts which part of the program is output.
_subsection: Disassembler Examples
A disassembled program shows offsets and mnemonics for the given
bytecode. This format may change in the future to be more
human-readable.
_code: @lang<shell>
/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
# Same as above