千家信息网

怎么使用Solidity Assembly

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要介绍"怎么使用Solidity Assembly",在日常操作中,相信很多人在怎么使用Solidity Assembly问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对
千家信息网最后更新 2026年10月31日怎么使用Solidity Assembly

这篇文章主要介绍"怎么使用Solidity Assembly",在日常操作中,相信很多人在怎么使用Solidity Assembly问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么使用Solidity Assembly"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1、使用Remix编辑器

首先,让我们将这个简单的合约粘贴到remix编辑器中:

pragma solidity ^0.5.10;contract AssemblyArrays {    bytes testArray;    function getLength() public view returns (uint256) {      return testArray.length;  }    function getElement(uint256 index) public view returns (bytes1) {      return testArray[index];  }    function pushElement(bytes1 value) public {      testArray.push(value);  }    function updateElement(bytes1 value, uint256 index) public {      testArray[index] = value;  }}

首先熟悉一下Remix编辑器。我们首先需要选择编译器版本,然后编译合约、部署合约,执行一些功能,然后调试。

2、第一行汇编代码

现在,让我们修改getLength函数来编写第一行汇编代码:

function getLength() public view returns (uint256) {  bytes memory memoryTestArray = testArray;  uint256 result;  assembly {    result := mload(memoryTestArray)  }  return result;}

上面几行代码中发生了很多事情。汇编就是这样,要实现一个非常简单的功能也需要很多代码。我们将testArray从存储复制到内存,因为这是本文的重点。以后我们可以再谈一谈存储插槽。

在深入探讨汇编语言块之前,请注意汇编指令是对32字节的字进行操作。因此,mload指令会将 memoryTestArray指向的内存位置的32个字节压入栈。。

3、Solidity汇编代码的断点设置与单步执行

现在调试一下。在Remix中,你可以通过单击行号来设置一个断点。让我们在第11行上设置一个断点,所以它看起来像这样:

更新getLength功能后,请确保已再次编译并重新部署了合约。现在,让我们调用pushElement函数将字节0x05插入数组,然后调用getLength,该函数应返回1。

调用getLength后我们可以对其进行调试。在底部面板的最后一个调用中单击"调试"按钮,这将在左侧栏中打开调试器。有一个用于快进的按钮(如:fast_forward:),它跳到下一个断点。让我们单击那个。如果你使用不同的编译器或不同的设置,那么对于你来说可能并不完全相同,但是其核心将是相同的。基本的思路是在mload执行之前获取调试器,在我的环境中是#0871指令。

4、查看Solidity汇编代码对栈的影响

现在让我们看一下调试器侧栏的栈/stack内容:

在堆栈顶部,位置0处为0x0...80。这是在内存中memoryTestArray的位置,该位置将作为mload指令的参数。

5、查看Solidity汇编代码对内存的影响

现在,让我们看一下调试器侧边栏的" 内存"部分,从地址0x0...80开始:

这里有31个字节0x00,后跟1个字节0x01,然后是1个字节0x05,后跟31个字节0x00。这可能有点令人困惑,所以让我们退后一点,注意1个字节(8位)由2个十六进制数字表示(1个十六进制数字表示4位)。同样,0x10十六进制的十进制等于16。因此,在内存中,位置0x80保存16个字节,位置0x90(0x80+ 0x10)保存随后的16个字节,然后位置0xa0(0x90+ 0x10)保存以下16个字节,而位置0xb0保存最后的16个字节。因为汇编中的指令以32字节为单位操作,所以如果我们调用mload(0x80),它将从内存位置0x80开始取32字节放入栈。

6、单步执行mload指令

让我们看看实际执行情况。让我们单击调试器中的"单步进入"按钮(即向下的箭头)来执行mload指令。现在看一下栈顶:

mload指令取栈顶内容:0x0...80,然后将内存中位置0x0...1的32个字节压入,这是了解内存中的字节数组最重要的一点:前32个字节存储数组的长度。

尝试调用pushElement函数将元素0x06插入数组。然后调用getLength并再次调试。同样,mload将从内存位置0x80开始载入32个字节,但是这次内存的内容为0x0...2。当我们追加新元素时,Solidity为我们更新了数组的大小。

内存中发生变化的另一件事是,现在位置0xa0是0x050600...00。因此,在内存中,一个字节数组变量在前32个字节存储其长度,然后开始存储具体的成员。首先我们压入0x05,然后又压入0x06。

7、用Solidity汇编重写getLength方法

尝试再压入一些元素,调用getLength并调试,以查看内存中的新字节。如果我们将getElement 转换为汇编,这个过程将变得更加清晰:

function getElement(uint256 index) public view returns (bytes1) {    uint256 length = getLength();    require(index < length);    bytes memory memoryTestArray = testArray;    bytes1 result;    assembly {      let wordIndex := div(index, 32)      let initialElement := add(memoryTestArray, 32)      let resultWord := mload(add(initialElement, mul(wordIndex, 32)))      let indexInWord := mod(index, 32)      result := shl(mul(indexInWord, 8), resultWord)    }    return result;}

好吧,这可能有点吓到你了!让我们慢慢地捋一下。

第一件超级重要的事情是,我们添加了require语句来检查index并没有超出范围。这在调用mload时是至关重要的,我们需要确保要载入的内存位置是正确的,否则可能就会泄漏调用者不应该访问的信息,这可能会让我们的合约存在严重的受攻击风险。

接下来,让我们看一下汇编代码块。由于mload一次读取32个字节,因此仅读取1个字节并不容易。如果我们把index除以32并取整,这将得到要查找的成员所在的32字节的序号。例如:

div(0, 32) = 0div(18, 32) = 0div(32, 32) = 1div(65, 32) = 2

看起来还不错。但是请记住,内存中memoryTestArray指向的内置的第一个字(32字节)是存储数组长度的。因此,我们需要加上32个字节来查找第一个数组成员。考虑到所有这些因素后,我们就可以载入包含我们需要的1个字节的字(32字节):

memoryTestArray的内存位置加上32个字节以跳过数组长度,再加wordIndex上乘以32,因为每个字都有32个字节。

但是还没有完成。现在我们需要从这个字中恰好提取1个字节。为此,我们需要在字中找到该字节的索引。这是字索引除以32的余数部分,可以通过mod指令获得。例如:

mod(0, 32) = 0mod(18, 32) = 18mod(32, 32) = 0mod(65, 32) = 1

不错,下面让我们完成最后一步,提取该字节。为了让字节在最前面,我们向左移动需要的位数。shl指令一次移动一位,所以为了移动指定的位数,我们要把indexInWord乘以8。

一旦我们将以这个字节开头的32个字节的字赋值给result变量,它就会删除所有其他字节,因为 我们将其类型声明为bytes1。

到此,关于"怎么使用Solidity Assembly"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

字节 内存 位置 指令 代码 数组 存储 合约 调试器 函数 断点 长度 学习 编译 重要 元素 内容 功能 十六进制 成员 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司排名 科技互联网企业 互联网科技战争 网络科技有限互联网 北京互联网科技有限公司 互联网 科技创业 互联网前沿科技 广州慧亚互联网科技怎么样 企晟互联网信息科技有限公司 佛山市拉法互联网科技有限公司 长沙茂晟互联网科技有限公司 伊宁互联网科技做什么的 滨湖区互联网智能科技产品有哪些 山东子淼互联网科技有限公司 厦门江牛科技互联网 互联网安防科技感 云鲸互联网络科技有限公司 悟空问答互联网科技 杭州科技互联网公司有哪些 知域互联网科技有限公司官网 花魁咖啡 广州淘业互联网络科技 深圳卡尔迅互联网科技有限公司怎么样 济南和联互联网科技有限公司 上海电发互联网科技有限公司 开启互联网科技时代小说 中化能源互联网科技招聘 苏州铭阳互联网科技有限公司 互联网科技品牌 六子台科技互联网展会
0