ethereum - solc 的 --opcodes 和 --asm 有什么区别?
问题描述
我正在学习低级 Solidity 内联汇编,但对不同的输出格式感到困惑。
Solidity 编译器的输出选项说:
--asm EVM assembly of the contracts.
--opcodes Opcodes of the contracts.
我尝试了两种选择来编译下面的合同:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract MyContract {
string bar = "Hello World";
function foo() public view returns(string memory) {
return bar;
}
}
该命令solc -o output --asm contract.sol
生成 MyContract.evm:
/* "contract.sol":70:208 contract MyContract {... */
mstore(0x40, 0x80)
/* "contract.sol":96:122 string bar = "Hello World" */
mload(0x40)
dup1
0x40
add
0x40
mstore
dup1
0x0b
dup2
mstore
0x20
add
0x7657399374655890603765000000000000000000000000000000000000000000
dup2
mstore
pop
0x00
swap1
dup1
mload
swap1
0x20
add
swap1
tag_1
swap3
swap2
swap1
tag_2
jump // in
tag_1:
pop
/* "contract.sol":70:208 contract MyContract {... */
callvalue
dup1
... (and a lot more code)
该命令solc -o output --opcodes contract.sol
生成 MyContract.opcode:
PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0xB DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x7657399374655890603765000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x0 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH2 0x4F SWAP3 SWAP2 SWAP1 PUSH2 0x62 JUMP JUMPDEST POP CALLVALUE DUP1 ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x166 JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH2 0x6E SWAP1 PUSH2 0x105 JUMP JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH2 0x90 JUMPI PUSH1 0x0 DUP6 SSTORE PUSH2 0xD7 JUMP JUMPDEST DUP3 PUSH1 0x1F LT PUSH2 0xA9 JUMPI DUP1 MLOAD PUSH1 ... ...
它们看起来非常相似,虽然不是 100% 相互匹配......
问题
- 与输出相比,是否
--opcodes
只是提供更紧凑的汇编代码形式--asm
? PUSH1 0x80 PUSH1 0x40 MSTORE
--opcodes
格式 与格式mstore(0x40, 0x80)
。--asm
他们在做同样的事情吗?(我猜是这样,但不是 100% 肯定......)- 有没有办法以
--opcodes
漂亮的格式而不是单行打印? - 有没有什么好的资源来学习 Solidity 内联汇编?我四处搜索,但发现了一堆单页博客,它们很好地解释了基础知识,但不幸的是,它们都没有提供完整而深入的教程
解决方案
1.与输出
--opcodes
相比,是否只是提供更紧凑的汇编代码形式--asm
?
这有点正确。您仍然可以将程序集转换为操作码并获得相同的结果。
汇编代表一组“低级”指令。操作码是传递给 EVM 的“真实”二进制指令。例如,请参见将操作码转换为二进制的此表。
2.格式
PUSH1 0x80 PUSH1 0x40 MSTORE
与格式。他们在做同样的事情吗?(我猜是这样,但不是 100% 肯定......)--opcodes
mstore(0x40, 0x80)
--asm
是的,他们正在做同样的事情 - 请参阅 1 的答案。当您在 Solidity 中运行此代码段时
assembly {
mstore(0x40, 0x80)
}
你得到相同的操作码。
3. 有没有办法以
--opcodes
漂亮的格式打印而不是单行打印?
您可以tr
在任何其他文本格式的 unix cli 命令上使用。
echo "PUSH1 0x80 PUSH1" | tr ' ' '\n'
PUSH1
0x80
PUSH1
有关更多方法,请参阅此论坛帖子。
4、有没有什么好的学习Solidity内联汇编的资源?
除了文档,我什么都不知道,所以我会让其他人给出更好的答案。但是 Solidity 仍然是一项相当新的技术,所以我的猜测是,大多数专门从事 Solidity 组装的人都是通过反复试验学习的。
推荐阅读
- swift - 带有可重用组件的 Swift UITableViewCell
- c - 基于另一个变量设置一组变量的有效方法?
- java - Eclipse 4.7.3a 和 Java 10 错误:找不到或加载主类
- php - 基于特定条件对数据进行分组的mysql查询
- c# - 如何在 Android Image Gallery 中保存统一拍摄的照片?
- ios - 获取“任何”类型的错误值没有成员“值”
- javascript - JavaScript:获取数组中的平均对象?
- java - 软引用在java中GC的作用
- node.js - nodejs中的ibm App ID注销
- .net - 如何在 webapi 控制器方法 C# 中检索已缓存的数据