[Ethereum] Understanding solidity inline assembly code

assemblyopcodesolidity

Here is a code from solidity documentation:

 function sumAsm(uint[] _data) public returns (uint o_sum) {
        for (uint i = 0; i < _data.length; ++i) {
            assembly {
                o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
            }
        }
    }

Can any one explain this code.
_data is an array of uint. How are can we add 0x20 to an array. If the array name represents the address of first element why are we offsetting it? How does this line (add(add(_data, 0x20), mul(i, 0x20))) give the address of the first and the subsequent elements of the array.

Best Answer

Within the assembly code, _data is the memory address of the start of the array data.

However, the first memory word (32 bytes = 0x20 bytes) is reserved for the length of the array, so we need to step over this. Thus, _data[0] is at memory address _data + 0x20. In the code, this looks like add(_data, 0x20).

The array elements follow consecutively, numbered from 0, each occupying one 32 byte (0x20 byte) word. Thus, element [N] is offset N * 0x20 from the start of the array data that we found above. In the code this offset is mul(i, 0x20).

Putting it all together, _data[i] is found at (_data + 0x20) + (i * 0x20), which is the expression (add(add(_data, 0x20), mul(i, 0x20))).

The net effect of the loop is to add up all the array elements into o_sum. It is likely done in assembly to avoid the overhead of array bounds checking that Solidity always inserts.

Related Topic