Ethereum Solidity Assembly、mstore函数和字的宽度(以字节为单位)

Ethereum Solidity Assembly、mstore函数和字的宽度(以字节为单位),ethereum,solidity,smartcontracts,evm,Ethereum,Solidity,Smartcontracts,Evm,我正在学习Solidity Assembly,我对一些事情感到困惑。我在看一个叫做Seriality的库。具体而言,此功能: 该函数bytes32ToBytes接受一个bytes32变量并将其存储在一个动态大小的字节数组中,从传入的偏移量开始 让我困惑的是,它两次使用mstore函数。但是mstore函数存储一个字,即32字节,对吗?既然输入是32字节,为什么要调用两次呢?两次调用不会存储2个字,即64字节吗 谢谢 通过将阵列大小写入第一个存储插槽,然后将数据写入后续插槽来存储Solidity阵

我正在学习Solidity Assembly,我对一些事情感到困惑。我在看一个叫做Seriality的库。具体而言,此功能:

该函数bytes32ToBytes接受一个bytes32变量并将其存储在一个动态大小的字节数组中,从传入的偏移量开始

让我困惑的是,它两次使用mstore函数。但是mstore函数存储一个字,即32字节,对吗?既然输入是32字节,为什么要调用两次呢?两次调用不会存储2个字,即64字节吗


谢谢

通过将阵列大小写入第一个存储插槽,然后将数据写入后续插槽来存储Solidity阵列

知道
mstore
具有以下参数:
mstore(开始位置,项到存储)
,第一条mstore语句编写如下:

mstore(add(_output, _offst), _input)
由于数组的第一个插槽指向数组的大小,因此此语句设置
\u输出的大小。通过将其替换为
mstore(add(\u output,\u offst),32)
(因为大小是
\u input
是静态的),您应该能够获得相同的结果

第二条语句(
mstore(add(add(\u output,\u offst),32),add(\u input,32))
)是写入数据本身的语句。这里,我们将两个指针的位置移动32个字节(因为两个数组的前32个字节都指向大小),并将
\u input
的值存储到
\u output
的数据存储位置

调用此方法之前,
\u输出
可能已经初始化(因此长度已经设置),因此通常不需要。但是,这并不痛。请注意,做出此假设的类似实现如下所示:

function test() public pure returns (bytes) {
    bytes32 i = "some message";
    bytes memory o = new bytes(32); // Initializing this way sets the length to the location "o" points to. This replaces mstore(add(_output, _offst), _input).
    bytes32ToBytes(0, i, o);
    
    return o;
}

function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
    assembly {
        mstore(add(add(_output, _offst),32), add(_input,32))
    }
}
function test() public pure returns (bytes) {
    bytes32 i = "some message";
    bytes memory o = new bytes(32); // Initializing this way sets the length to the location "o" points to. This replaces mstore(add(_output, _offst), _input).
    bytes32ToBytes(0, i, o);
    
    return o;
}

function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
    assembly {
        mstore(add(add(_output, _offst),32), add(_input,32))
    }
}