diff options
author | chriseth <c@ethdev.com> | 2017-01-04 19:58:35 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2017-01-04 19:58:35 +0800 |
commit | e92af89ec8563334ddb9aa8f208a249c149b3092 (patch) | |
tree | 42809a2f8f0937bf3cccff956abd2d50effdaebe | |
parent | 4bc934abce48a6c30cdaa9f4cbf7dae15f292831 (diff) | |
download | dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar.gz dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar.bz2 dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar.lz dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar.xz dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.tar.zst dexon-solidity-e92af89ec8563334ddb9aa8f208a249c149b3092.zip |
Typos and clarifications.
-rw-r--r-- | docs/assembly.rst | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/docs/assembly.rst b/docs/assembly.rst index 255ad3e6..2d868e4d 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -29,7 +29,7 @@ arising when writing manual assembly by the following features: * labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))`` * loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }`` * switch statements: ``switch x case 0: { y := mul(x, 2) } default: { y := 0 }`` -* function calls: ``function f(x) -> (y) { switch x case 0: { y := 1 } default: y := mul(x, f(sub(x, 1))) }`` +* function calls: ``function f(x) -> (y) { switch x case 0: { y := 1 } default: { y := mul(x, f(sub(x, 1))) } }`` .. note:: Of the above, loops, function calls and switch statements are not yet implemented. @@ -69,7 +69,7 @@ idea is that assembly libraries will be used to enhance the language in such way Inline assembly 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 -the compiler does not perform checks, so you should use it for complex things only if +the compiler does not perform checks, so you should use it only if you really know what you are doing. .. code:: @@ -88,7 +88,7 @@ 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), i)) + o_sum := mload(add(add(_data, 0x20), mul(i, 0x20))) } } } @@ -109,7 +109,7 @@ to write assembly programs that do not make use of explicit ``SWAP``, ``DUP``, ``JUMP`` and ``JUMPI`` statements, because the first two obfuscate the data flow and the last two obfuscate control flow. Furthermore, functional statements of the form ``mul(add(x, y), 7)`` are preferred over pure opcode statements like -``7 x y add mul`` because in the first form, it is much easier to see which +``7 y x add mul`` because in the first form, it is much easier to see which operand is used for which opcode. The second goal is achieved by introducing a desugaring phase that only removes @@ -131,11 +131,14 @@ outer assembly is visible in a sub-assembly. If control flow passes over the end of a block, pop instructions are inserted that match the number of local variables declared in that block, unless the ``}`` is directly preceded by an opcode that does not have a continuing control -flow path. The stack height is reduced by the number of local variables -regardless of that. This mean that labels in the next block will have the -same height as before the block that just ended. - -If at the end of a block, the stack is not balanced, a warning is issued, +flow path. Whenever a local variable is referenced, the code generator needs +to know its current relative position in the stack and thus it needs to +keep track of the current so-called stack height. +At the end of a block, this implicit stack height is always reduced by the number +of local variables whether ther is a continuing control flow or not. + +This means that the stack height before and after the block should be the same. +If this is not the case, a warning is issued, unless the last instruction in the block did not have a continuing control flow path. Why do we use higher-level constructs like ``switch``, ``for`` and functions: @@ -160,7 +163,7 @@ We consider the runtime bytecode of the following Solidity program:: contract C { function f(uint x) returns (uint y) { - y = 1 + y = 1; for (uint i = 0; i < x; i++) y = 2 * y; } @@ -228,6 +231,7 @@ After the desugaring phase it looks as follows:: $fun_allocate: { $start[$retpos, size]: + // output variables live in the same scope as the arguments. let pos := 0 { pos := mload(0x40) @@ -261,7 +265,7 @@ Syntax ------ Inline assembly parses comments, literals and identifiers exactly as Solidity, so you can use the -usual ``//`` and ``/* */`` comments. Inline assembly is initiated by ``assembly { ... }`` and inside +usual ``//`` and ``/* */`` comments. Inline assembly is marked by ``assembly { ... }`` and inside these curly braces, the following can be used (see the later sections for more details) - literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) @@ -778,8 +782,8 @@ Grammar:: AssemblySwitch = 'switch' FunctionalAssemblyExpression AssemblyCase* ( 'default' ':' AssemblyBlock )? AssemblyCase = 'case' FunctionalAssemblyExpression ':' AssemblyBlock - AssemblyFunctionDefinition = 'function' Identifier '(' IdentifierList? ')' '->' - ( '(' IdentifierList ')' AssemblyBlock + AssemblyFunctionDefinition = 'function' Identifier '(' IdentifierList? ')' + ( '->' '(' IdentifierList ')' )? AssemblyBlock AssemblyFor = 'for' ( AssemblyBlock | FunctionalAssemblyExpression) FunctionalAssemblyExpression ( AssemblyBlock | FunctionalAssemblyExpression) AssemblyBlock SubAssembly = 'assembly' Identifier AssemblyBlock |