Cover photo

[译]Solidity中的内联汇编Inline Assembly介绍

原文: Solidity Tutorial : all about Assembly

什么是汇编?

任何以高级语言(例如C,Go或Java)编写的程序,在执行之前都将先编译为“汇编语言”。

汇编(又称汇编语言)是指可使用汇编器转换为机器代码的低级编程语言。汇编语言与物理机或虚拟机绑定,因为它们实现了指令集。一条指令告诉CPU执行一些基本任务,例如将两个数字相加。

为什么Solidity中需要汇编?

1. 细粒度控制

你可以使用操作码直接与EVM进行交互。 这使的可以对程序(=智能合约)要执行的操作进行更精细控制。

汇编提供了更多控制权来执行某些仅靠Solidity不可能实现的逻辑。 例如,指向特定的内存插槽。

当编写库时,细粒度控制特别有用,因为这些将被开发人员重用。

2. 更少的Gas消耗

让我们通过创建简单的函数来比较Solidity和Assembly之间的Gas成本:1)简单地将两个数字(x + y)相加,然后2)返回结果。

function addAssembly(uint x, uint y) public pure returns (uint) {
     assembly {
         // Add some code here
         let result := add(x, y)
         mstore(0x0, result)
         return(0x0, 32)
     }
 }
 
 function addSolidity(uint x, uint y) public pure returns (uint) {
     return x + y;
 }
post image

从上面的示例中可以看到,使用内联汇编可以节省86的gas。 对于此示例来说,这并不是很多,但这粗略地了解了我们可以为更复杂的合约节省多少gas。

3. 增强功能

有一些事情在EVM汇编中可以做,而没法在Solidity中实现。例子

Solidity中的两种类型的汇编

  1. 内联汇编(Inline Assembly):可以再内部Solidity源代码中使用;

  2. 独立汇编(Standalone Assembly):可以直接使用,无需Solidity.

基本汇编语法

可以在Solidity中使用assembly{} 来嵌入汇编代码,这就是内联汇编:

contract Assembler { 
 function do_something_cpu() public {
   assembly {
     // start writing evm assembler language
   }
 }
}

assembly 块内的代码开发语言被称为Yul。

汇编代码块之间不能通信,也就是说在 一个汇编代码块里定义的变量,在另一个汇编代码块中不可以访问。

简单汇编示例

下面的代码使用内联汇编代码计算函数的两个参数的和并返回结果:

function addition(uint x, uint y) public pure returns (uint) { 
 assembly { 
     // 创建一个新的变量result
     //     -> 使用add操作码计算x+y
     //     -> 将计算结果赋值给变量result 
     let result := add(x, y)   // x + y 
      
     // 使用mstore操作码
     //     -> 将result变量的值存入内存
     //     -> 指定内存地址 0x0 
     mstore(0x0, result)       // 将结果存入内存
      
     // 从内存地址0x返回32字节
     return(0x0, 32) 
 }
}

更多技术细节请参阅原文。

编写汇编的缺点

Solidity文档指出以下内容:

内联汇编是一种以较低级别访问以太坊虚拟机的方法。 这绕过了几个重要的安全功能和Solidity的检查。 仅当您有信心及必需时才使用它。

汇编中都是uint

EVM汇编中的算术运算忽略了某些类型可以小于256位的(例如:uint64)。

例如,一个地址长20个字节。 你还可以在Solidity中指定较小的类型,例如bytes10uint128

为了提高效率,EVM汇编将每个值都视为256位数字。高阶位仅在必要时才清除(例如:执行比较或写入内存之前)

这意味着,如果您从内联汇编中访问此类变量,则可能必须先手动清除高阶位。编写汇编代码会很快成为负担。

参考

https://ethereum.stackexchange.com/questions/54733/compile-standalone-assembly

https://docs.soliditylang.org/en/v0.6.2/yul.html#evm-dialect

https://solidity-cn.readthedocs.io/zh/develop/assembly.html#inline-assembly


我的推特:

https://twitter.com/LuSicong