如何理解Solidity的Bytecode和Opcode

技术如何理解Solidity的Bytecode和Opcode本篇文章为大家展示了如何理解Solidity的Bytecode和Opcode,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收

本文向您展示了如何理解Solidity的字节码和操作码。内容简洁易懂,一定会让你眼前一亮。希望通过这篇文章的详细介绍,你能有所收获。

可靠性的字节码和操作码

当我们更深入地编写智能合约时,我们会遇到诸如“PUSH1”、“SSTORE”和“CALLVALUE”等术语。它们是什么,我们应该在什么时候使用它们?

要理解这些命令,我们必须对以太网虚拟机(EVM)有更深的理解。本文将试图尽可能简单地解释一些EVM基础知识。希望大家都有所收获。

像许多其他流行的编程语言一样,Solidity是一种高级编程语言。我们可以阅读它,但是机器不能。如果你学过java、C、C等编程语言,应该很容易理解这个道理。

当我们安装Ethereum客户端如geth时,它还附带了Ethereum虚拟机,这是一个专门为运行智能合约而创建的轻量级操作系统。

当我们用solc编译器编译Solidity代码时,它会将代码转换成只有EVM才能理解的字节码。

让我们以一个非常简单的合同为例:

pragmasolidity^0.4.26;

contractOpcodeContract{

uinti=(10 ^ 2)* 2;

}如果我们在remix浏览器中运行这段代码,点击Contract Details,会看到很多信息。

如何理解Solidity的Bytecode和Opcode

在这种情况下,编译后的代码是:

字节码

{

linkReferences':{},

对象' : ' 6080604052601860005534801560145760080 FD 5b 5060358060226000396000300306060405260008000000000000000000000000000000000165627 a 7a 72305820 db 567e 501 f 168282876 df 36e eee

操作码' : ' push 10 X80 push 10 x40 msorebush 10 x18 push 10 x0sstorcallvaluedup1 iszeropush 10 x14 jumpipush 10 x0 dup1 evertjumpdestpopush 10 x35 dup1 push 10 x22 push 10x0 codecopypush 10 x0 returnstopush 10 X80 push 10 x40 msorebush 10 dup1 evertstolpog1 push 60 x627 a 723058 kecca 2560 xdsarjumpush 310 x501 f 16822

source map ' : ' 25:5433600:-;64:12;55:21;25:54;8:9:-1;5:2;30:1;27;20:12;5:2;25:54:0;'

}其中object是编译后的代码。它们是最终契约的十六进制表示,也称为字节码。

在remix浏览器的“Web3部署”部分,我们看到:

varopcodecontract contract=web 3 . eth . contract([]);

varopcodecontract=opcodecontract . new(

{

from: web3.eth.accounts[0], 
     data: '0x60806040526018600055348015601457600080fd5b5060358060226000396000f3006080604052600080fd00a165627a7a72305820db1d567e501f1682876df36eea80a02d25a8b2adb186da705e2e98e134b08cc60029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

简单来说,这意味着当我们部署合同时,我们需要将编译后的16进制码当成data传递,并且建议的gas为4700000。

任何以“ 0x”开头的内容都表示该值采用十六进制格式。 十六进制前面的“ 0x”并不是强制的,因为EVM会将任何值都视为十六进制。

我们还看到了操作代码(又称Opcode):

"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x18 PUSH1 0x0 SSTORE CALLVALUE DUP1 ISZERO PUSH1 0x14 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x35 DUP1 PUSH1 0x22 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xdb SAR JUMP PUSH31 0x501F1682876DF36EEA80A02D25A8B2ADB186DA705E2E98E134B08CC6002900 ",

操作码是程序的低级可读指令。 所有操作码都具有对应的十六进制值,例如“ MSTORE”为“ 0x52”,SSTORE”为“ 0x55”……等等。

具体的操作码对应的数值可以参考以太坊相关资料。

EVM虚拟机是一中堆栈虚拟机,所谓堆栈就是后进先出结构,用计算机科学术语来说,我们称为LIFO。

举个例子,上面的智能合约,如果在普通算术中,我们这样写方程式:

// Answer is 14. we do multiplication before addition.
10 + 2 * 2

在EVM堆栈虚拟机中,它按照LIFO原理工作,所以我们需要这样写:

2 2 * 10 +

这意味着,首先将“ 2”放入堆栈,然后再放入另一个“ 2”,然后再进行乘法运算。 结果是“ 4”放在在堆栈顶部。 现在在“ 4”的顶部加上数字“ 10”,最后将两个数字加在一起。 堆栈的最终值为14。

这种算术类型称为后缀表示法。

将数据放入堆栈的动作称为“ PUSH”指令,将数据从堆栈中删除的动作称为“ POP”指令。 很明显,我们在上面的示例中看到的最常见的操作码是“ PUSH1”,这意味着将1个字节的数据放入堆栈中。
因此,此指令:

PUSH1 0x80

表示将1字节值“ 0x80”放入堆栈中。 “ PUSH1”的十六进制值恰是“ 0x60”。 删除非强制性的“ 0x”,我们可以将此逻辑以字节码形式写为“ 6080”。
让我们更进一步。

PUSH1 0x80 PUSH1 0x40 MSTORE

再次查看以太坊的操作码图表,我们看到MSTORE(0x52)接受2个输入,但不产生任何输出。 上面的操作码表示:
PUSH1(0x60):将0x80放入堆栈。
PUSH1(0x40):将0x40放入堆栈。
MSTORE(0x52):分配0x80的内存空间并移至0x40的位置。
结果字节码为:

6080604052

实际上,在任何固定字节码的开头,我们总会看到这个魔术数字“ 6080604052”,因为它是智能合约引导的方式。

请注意,这里不能将0x40或0x60解释为实数40或60。由于它们是十六进制,所以40实际上等于十进制的64(16 x 4),而80等于十进制的128(16 x 8)。

简而言之,“ PUSH1 0x80 PUSH1 0x40 MSTORE”正在做的是分配128个字节的内存并将指针移到第64个字节的开头。现在,我们有64个字节用于暂存空间,而64个字节用于临时内存存储。

在EVM中,有3个地方可以存储数据。首先,在堆栈中,按照上面的示例,我们刚刚使用了“ PUSH”操作码在此处存储数据。其次,在使用“ MSTORE”操作码的内存(RAM)中,最后在使用“ SSTORE”存储数据的磁盘存储中。将数据存储到磁盘存储所需的gas最昂贵,而将数据存储到堆栈中的gas则最便宜。

我们在Solidity中的智能合约中,有时候也会用到Assembly Language,这个Assembly Language就是使用这样的汇编Opcode来操作EVM字节码。他理解起来比较难,但是通过使用它可以节省燃料和做一些无法通过Solidity完成的事情。

上述内容就是如何理解Solidity的Bytecode和Opcode,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/112496.html

(2)

相关推荐

  • 手工纸灯笼制作,幼儿园手工制作灯笼需要什么材

    技术手工纸灯笼制作,幼儿园手工制作灯笼需要什么材准备材料手工纸灯笼制作:一次性纸杯两只,红线若干,剪刀,胶水或双面胶,放焰火剩余的手柄,红色颜料和水粉笔。具体步骤:1.取一只纸杯,尽量选择横竖有参考图案的。沿纵向条纹均匀

    生活 2021年10月30日
  • 如何选择好的虚拟主机或者网站空间

    技术如何选择好的虚拟主机或者网站空间这篇文章主要为大家展示了“如何选择好的虚拟主机或者网站空间”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何选择好的虚拟主机或者网站空间”

    攻略 2021年11月1日
  • 如何理解互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

    技术如何理解互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景本篇内容主要讲解“如何理解互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家

    攻略 2021年10月22日
  • 描写夜晚环境的句子,晚上环境描写的句子关于亲情的

    技术描写夜晚环境的句子,晚上环境描写的句子关于亲情的父亲出门的时候描写夜晚环境的句子,月亮还没下山。父亲回家的时候,月亮早就上山了。五岁那年,我浑身长满了水痘,每天都要去医院打针,从家到医院大约有三四里路,每次去父亲总把

    生活 2021年10月26日
  • 如何理解ansible自动化运维数据库

    技术如何理解ansible自动化运维数据库这期内容当中小编将会给大家带来有关如何理解ansible自动化运维数据库,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。 通过ansible

    攻略 2021年11月12日
  • fedora安装软件命令(fedora u盘安装)

    技术fedora 16下如何安装使用mysql小编给大家分享一下fedora 16下如何安装使用mysql,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了

    攻略 2021年12月18日