aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/control-structures.rst194
1 files changed, 97 insertions, 97 deletions
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 5a22cbe3..49d12087 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -246,8 +246,8 @@ arising when writing manual assembly by the following features:
We now want to describe the inline assembly language in detail.
.. warning::
- Inline assembly is still a relatively new feature and might change if it does not prove useful,
- so please try to keep up to date.
+ Inline assembly is still a relatively new feature and might change if it does not prove useful,
+ so please try to keep up to date.
Example
-------
@@ -258,23 +258,23 @@ idea is that assembly libraries will be used to enhance the language in such way
.. code::
- library GetCode {
- function at(address _addr) returns (bytes o_code) {
- assembly {
- // retrieve the size of the code, this needs assembly
- let size := extcodesize(_addr)
- // allocate output byte array - this could also be done without assembly
- // by using o_code = new bytes(size)
- o_code := mload(0x40)
- // new "memory end" including padding
- mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
- // store length in memory
- mstore(o_code, size)
- // actually retrieve the code, this needs assembly
- extcodecopy(_addr, add(o_code, 0x20), 0, size)
- }
- }
- }
+ library GetCode {
+ function at(address _addr) returns (bytes o_code) {
+ assembly {
+ // retrieve the size of the code, this needs assembly
+ let size := extcodesize(_addr)
+ // allocate output byte array - this could also be done without assembly
+ // by using o_code = new bytes(size)
+ o_code := mload(0x40)
+ // new "memory end" including padding
+ mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), bnot(0x1f))))
+ // store length in memory
+ mstore(o_code, size)
+ // actually retrieve the code, this needs assembly
+ extcodecopy(_addr, add(o_code, 0x20), 0, size)
+ }
+ }
+ }
Inline assemmbly could also be beneficial in cases where the optimizer fails to produce
efficient code. Please be aware that assembly is much more difficult to write because
@@ -283,24 +283,24 @@ you really know what you are doing.
.. code::
- library VectorSum {
- // This function is less efficient because the optimizer currently fails to
- // remove the bounds checks in array access.
- function sumSolidity(uint[] _data) returns (uint o_sum) {
- for (uint i = 0; i < _data.length; ++i)
- o_sum += _data[i];
- }
- // We know that we only access the array in bounds, so we can avoid the check.
- // 0x20 needs to be added to an array because the first slot contains the
- // array length.
- function sumAsm(uint[] _data) returns (uint o_sum) {
- for (uint i = 0; i < _data.length; ++i) {
- assembly {
+ library VectorSum {
+ // This function is less efficient because the optimizer currently fails to
+ // remove the bounds checks in array access.
+ function sumSolidity(uint[] _data) returns (uint o_sum) {
+ for (uint i = 0; i < _data.length; ++i)
+ o_sum += _data[i];
+ }
+ // We know that we only access the array in bounds, so we can avoid the check.
+ // 0x20 needs to be added to an array because the first slot contains the
+ // array length.
+ function sumAsm(uint[] _data) returns (uint o_sum) {
+ for (uint i = 0; i < _data.length; ++i) {
+ assembly {
o_sum := mload(add(add(_data, 0x20), i))
}
}
- }
- }
+ }
+ }
Syntax
------
@@ -487,7 +487,7 @@ Strings are stored left-aligned and cannot be longer than 32 bytes.
.. code::
- assembly { 2 3 add "abc" and }
+ assembly { 2 3 add "abc" and }
Functional Style
-----------------
@@ -497,7 +497,7 @@ adding `3` to the contents in memory at position `0x80` would be
.. code::
- 3 0x80 mload add 0x80 mstore
+ 3 0x80 mload add 0x80 mstore
As it is often hard to see what the actual arguments for certain opcodes are,
Solidity inline assembly also provides a "functional style" notation where the same code
@@ -505,7 +505,7 @@ would be written as follows
.. code::
- mstore(0x80, add(mload(0x80), 3))
+ mstore(0x80, add(mload(0x80), 3))
Functional style and instructional style can be mixed, but any opcode inside a
functional style expression has to return exactly one stack slot (most of the opcodes do).
@@ -536,18 +536,18 @@ It is planned that the stack height changes can be specified in inline assembly.
.. code::
- contract c {
- uint b;
- function f(uint x) returns (uint r) {
- assembly {
- b pop // remove the offset, we know it is zero
- sload
- x
- mul
- =: r // assign to return variable r
- }
- }
- }
+ contract c {
+ uint b;
+ function f(uint x) returns (uint r) {
+ assembly {
+ b pop // remove the offset, we know it is zero
+ sload
+ x
+ mul
+ =: r // assign to return variable r
+ }
+ }
+ }
Labels
------
@@ -558,19 +558,19 @@ jumps easier. The following code computes an element in the Fibonacci series.
.. code::
- {
- let n := calldataload(4)
- let a := 1
- let b := a
- loop:
- jumpi(loopend, eq(n, 0))
- a add swap1
- n := sub(n, 1)
- jump(loop)
- loopend:
- mstore(0, a)
- return(0, 0x20)
- }
+ {
+ let n := calldataload(4)
+ let a := 1
+ let b := a
+ loop:
+ jumpi(loopend, eq(n, 0))
+ a add swap1
+ n := sub(n, 1)
+ jump(loop)
+ loopend:
+ mstore(0, a)
+ return(0, 0x20)
+ }
Please note that automatically accessing stack variables can only work if the
assembler knows the current stack height. This fails to work if the jump source
@@ -583,19 +583,19 @@ will have a wrong impression about the stack height at label `two`:
.. code::
- {
- jump(two)
- one:
- // Here the stack height is 1 (because we pushed 7),
- // but the assembler thinks it is 0 because it reads
- // from top to bottom.
- // Accessing stack variables here will lead to errors.
- jump(three)
- two:
- 7 // push something onto the stack
- jump(one)
- three:
- }
+ {
+ jump(two)
+ one:
+ // Here the stack height is 1 (because we pushed 7),
+ // but the assembler thinks it is 0 because it reads
+ // from top to bottom.
+ // Accessing stack variables here will lead to errors.
+ jump(three)
+ two:
+ 7 // push something onto the stack
+ jump(one)
+ three:
+ }
Declaring Assembly-Local Variables
@@ -610,19 +610,19 @@ be just `0`, but it can also be a complex functional-style expression.
.. code::
- contract c {
- function f(uint x) returns (uint b) {
- assembly {
- let v := add(x, 1)
- mstore(0x80, v)
- {
- let y := add(sload(v), 1)
- b := y
- } // y is "deallocated" here
- b := add(b, v)
- } // v is "deallocated" here
- }
- }
+ contract c {
+ function f(uint x) returns (uint b) {
+ assembly {
+ let v := add(x, 1)
+ mstore(0x80, v)
+ {
+ let y := add(sload(v), 1)
+ b := y
+ } // y is "deallocated" here
+ b := add(b, v)
+ } // v is "deallocated" here
+ }
+ }
Assignments
@@ -640,12 +640,12 @@ For both ways, the colon points to the name of the variable.
.. code::
- assembly {
- let v := 0 // functional-style assignment as part of variable declaration
- let g := add(v, 2)
- sload(10)
- =: v // instruction style assignment, puts the result of sload(10) into v
- }
+ assembly {
+ let v := 0 // functional-style assignment as part of variable declaration
+ let g := add(v, 2)
+ sload(10)
+ =: v // instruction style assignment, puts the result of sload(10) into v
+ }
Things to Avoid
@@ -681,6 +681,6 @@ arrays are pointers to memory arrays. The length of a dynamic array is stored at
first slot of the array and then only the array elements follow.
.. warning::
- Statically-sized memory arrays do not have a length field, but it will be added soon
- to allow better convertibility between statically- and dynamically-sized arrays, so
- please do not rely on that.
+ Statically-sized memory arrays do not have a length field, but it will be added soon
+ to allow better convertibility between statically- and dynamically-sized arrays, so
+ please do not rely on that.