1.6.7 Solidity汇编语言

Solidity定义了一套汇编语言,这套语言可以独立于Solidity单独使用。这套汇编语言可以嵌在Solidity的源代码内作为内联汇编语言使用。

在编写库时,为了更好的控制和提高语言的效率,可以用虚拟机很容易解析的内联汇编语言和Solidity一起使用。虽然以太坊虚拟机是基于堆栈的,但要正确地处理堆栈并给操作码输入合适的参数也不容易。Solidity的内联汇编语言就很好地处理了这些问题。它有下列这些特性:

- 类函数风格的操作码:mul(1, add(2, 3)) 而不是push1 3 push1 2 add push1 1 mul。

- 局部汇编变量:let x := add(2, 3) let y := mload(0x40) x := add(x, y)。

- 访问外部变量:function f(uint x) public { assembly { x := sub(x, 1) } }。

- 标签(label):let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))。

- 循环:for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }。

- if语句:if slt(x, 0) { x := sub(0, x) }。

- switch语句:switch x case 0 { y := mul(x, 2) } default { y := 0 }。

- 函数调用:function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } }。

注意:内联汇编语言是直接和以太坊虚拟机交互的低级语言,为了效率牺牲了部分安全性能。

实际上内联汇编语言也可以脱离Solidity单独作为Solidity编译器的汇编语言使用,而且这也是其原本的规划。这样做主要是希望达到下面三个目的:

- 用汇编语言写的程序要有可读性,甚至对由用Solidity编写而经过编译器产生的汇编码都是如此。

- 从汇编再转换为字节码(bytecode)的过程应该尽量平滑,变化尽量小。

- 汇编语言写的代码其控制流程应该容易检查和审阅,以便对代码进行验证和优化。

关于Solidity汇编语言的细节可参考https://solidity.readthedocs.io/en/v0.4.24/assembly.html#