diff options
Diffstat (limited to 'docs/assembly.rst')
-rw-r--r-- | docs/assembly.rst | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/docs/assembly.rst b/docs/assembly.rst index 83643634..bdb708a9 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -92,10 +92,35 @@ you really know what you are doing. function sumAsm(uint[] _data) returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) { assembly { - o_sum := mload(add(add(_data, 0x20), mul(i, 0x20))) + o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) } } } + + // Same as above, but accomplish the entire code within inline assembly. + function sumPureAsm(uint[] _data) returns (uint o_sum) { + assembly { + // Load the length (first 32 bytes) + let len := mload(_data) + + // Skip over the length field. + // + // Keep temporary variable so it can be incremented in place. + // + // NOTE: incrementing _data would result in an unusable + // _data variable after this assembly block + let data := add(_data, 0x20) + + // Iterate until the bound is not met. + for + { let end := add(data, len) } + lt(data, end) + { data := add(data, 0x20) } + { + o_sum := add(o_sum, mload(data)) + } + } + } } @@ -110,7 +135,7 @@ these curly braces, the following can be used (see the later sections for more d - opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below - opcodes in functional style, e.g. ``add(1, mlod(0))`` - labels, e.g. ``name:`` - - variable declarations, e.g. ``let x := 7`` or ``let x := add(y, 3)`` + - variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned) - identifiers (labels or assembly-local variables and externals if used as inline assembly), e.g. ``jump(name)``, ``3 x add`` - assignments (in "instruction style"), e.g. ``3 =: x`` - assignments in functional style, e.g. ``x := add(y, 3)`` @@ -125,7 +150,7 @@ following list can be used as a reference of its opcodes. If an opcode takes arguments (always from the top of the stack), they are given in parentheses. Note that the order of arguments can be seen to be reversed in non-functional style (explained below). Opcodes marked with ``-`` do not push an item onto the stack, those marked with ``*`` are -special and all others push exactly one item onte the stack. +special and all others push exactly one item onto the stack. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to (excluding) position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``. @@ -490,7 +515,7 @@ is performed by replacing the variable's value on the stack by the new value. .. code:: - assembly { + { let v := 0 // functional-style assignment as part of variable declaration let g := add(v, 2) sload(10) @@ -509,7 +534,7 @@ case called ``default``. .. code:: - assembly { + { let x := 0 switch calldataload(4) case 0 { @@ -538,7 +563,7 @@ The following example computes the sum of an area in memory. .. code:: - assembly { + { let x := 0 for { let i := 0 } lt(i, 0x100) { i := add(i, 0x20) } { x := add(x, mload(i)) @@ -565,7 +590,7 @@ The following example implements the power function by square-and-multiply. .. code:: - assembly { + { function power(base, exponent) -> result { switch exponent case 0 { result := 1 } @@ -679,6 +704,8 @@ Example: We will follow an example compilation from Solidity to desugared assembly. We consider the runtime bytecode of the following Solidity program:: + pragma solidity ^0.4.0; + contract C { function f(uint x) returns (uint y) { y = 1; @@ -965,7 +992,7 @@ adjustment. Every time a new local variable is introduced, it is registered together with the current stack height. If a variable is accessed (either for copying its value or for assignment), the appropriate DUP or SWAP instruction is selected depending -on the difference bitween the current stack height and the +on the difference between the current stack height and the stack height at the point the variable was introduced. Pseudocode:: |