for (i = 0; i < words; i++) {
/* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
assembly {
let commonIndex := mul(0x20, add(1, i))
let maskValue := mload(add(mask, commonIndex))
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
}
}有人能帮我解释一下这些密码吗?谢谢
发布于 2022-04-26 12:46:11
好的,
这段代码是guardedArrayReplace函数的一部分,该函数实质上用另一个字节数组的内容覆盖字节数组的内容,但它可能会根据所提供的掩码而有所不同。
作为对按位操作的提醒,使用两个字节值作为解释:
假设我们有一个array值为0x1234,一个期望值为0xaabb,掩码为0x00FF。掩码将用于选择要从desired中获取哪些位以写入array。反转掩码可以让您从array中保留哪些位。
array & not(mask) = 0x1200:丢弃array中掩码未指向的值。
desired & mask = 0x00bb:只保留掩码在desired中指向的值。
将这两者结合起来:or(array & not(mask), desired & mask,我们得到0x12bb。在这里,我们有效地用来自array的desired值更新了mask所指出的值。
for (i = 0; i < words; i++) {
/* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
assembly {
let commonIndex := mul(0x20, add(1, i))
let maskValue := mload(add(mask, commonIndex))
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
}
}这个部分正在处理32个字节块,即使底层数据是以字节划分的。只要有可能,这只是一种一次性处理32种元素的方法。
let commonIndex := mul(0x20, add(1, i))计算在循环的特定迭代中处理的32个字节块的内存索引(或地址)。在第一次迭代中,我们的目标是内存索引0x20 (32) * (i + 1)的数据。+ 1只是用来跳过包含数组长度的前32个字节。
let maskValue := mload(add(mask, commonIndex))使用以下事实:array、mask和desired必须具有相同的长度(请参阅函数中的require语句),只需从mask数组加载当用desired中的特定部分覆盖array的特定部分时应该应用的32个字节。
mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))我们会把它拆开的:
mstore参数是:
add(array, commonIndex)or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex))))第一个是我们将要写入修改后的32个字节的地址,第二个是要写入的值。
or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex))))
其中,and(not(maskValue), mload(add(array, commonIndex)))接受来自array的值,并且只保留未被maskValue标记的字节。另一方面,and(maskValue, mload(add(desired, commonIndex)))接受来自desired的值,并且只保留由maskValue标记的字节。周围的or融合了我们想要从array中保留的东西和我们想从desired获取的东西。
然后在适当的32字节槽处用array写入此值。
这个过程被重复了尽可能多次,这样的话,更新一个大小为64字节(32 * 2)的数组只需要2次迭代,而不是64次,如果你要逐字节进行的话。
我希望这能回答你的问题。
https://ethereum.stackexchange.com/questions/126929
复制相似问题