任何以高级语言(例如C,Go或Java)编写的程序,在执行之前都将先编译为“汇编语言”。
汇编(又称汇编语言)是指可使用汇编器转换为机器代码的低级编程语言。汇编语言与物理机或虚拟机绑定,因为它们实现了指令集。一条指令告诉CPU执行一些基本任务,例如将两个数字相加。
你可以使用操作码直接与EVM进行交互。 这使的可以对程序(=智能合约)要执行的操作进行更精细控制。
汇编提供了更多控制权来执行某些仅靠Solidity不可能实现的逻辑。 例如,指向特定的内存插槽。
当编写库时,细粒度控制特别有用,因为这些将被开发人员重用。
让我们通过创建简单的函数来比较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;
}

从上面的示例中可以看到,使用内联汇编可以节省86的gas。 对于此示例来说,这并不是很多,但这粗略地了解了我们可以为更复杂的合约节省多少gas。
有一些事情在EVM汇编中可以做,而没法在Solidity中实现。例子
内联汇编(Inline Assembly):可以再内部Solidity源代码中使用;
独立汇编(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的检查。 仅当您有信心及必需时才使用它。
EVM汇编中的算术运算忽略了某些类型可以小于256位的(例如:uint64)。
例如,一个地址长20个字节。 你还可以在Solidity中指定较小的类型,例如bytes10或uint128。
为了提高效率,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
我的推特:

