Assembly

在彙編中操作單個字節

  • February 3, 2022

我正在學習彙編,我正在嘗試寫給數組bytes中的個人。bytes32我有以下程式碼:

contract TestAssembly {}
   function test(
       uint8 _count
   ) public {
       bytes32 bytesTest;
       assembly { 
           for { let i := 0} lt(i, _count) { i := add(i, 1) } { 
               mstore(add(bytesTest, i), 0x33)
           }
       }
   }
}

我希望這段程式碼會遍歷 中的每個字節bytesTest,並將每個字節替換為0x33,但bytesTest似乎沒有被修改。

在@Jesbus 評論的基礎上,這裡是一個實現你想要的評論範例:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TestAssembly {
   function test(uint8 _count) public pure returns (bytes memory) {

       // Declares the array in memory
       bytes memory bytesTest = new bytes(10);

       // Protect against buffer overflow
       require(_count <= 10, "not enough bytes in the array");

       assembly {

           // Skip the first 32 bytes reserved for the length of the memory array
           let offset := add(bytesTest, 0x20)

           // Loop _count times over the array
           for { let i := 0} lt(i, _count) { i := add(i, 1) } { 
               // Make use of mstore8 (1 byte) instead of mstore (32 bytes)
               mstore8(add(offset, i), 0x33)
           }
       }

       return bytesTest;
   }
}

編輯

我正在添加一個依賴於沒有長度前綴並使用 bytes32 的數組文字的範例。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TestAssembly {
   function test(uint8 _count) public pure returns (bytes32) {

       // Declares the byte32 array in memory : this is an array literal -> there is no length prefix
       bytes32[1] memory bytesTest = [bytes32(0)];

       // Protect against buffer overflow
       require(_count <= 32, "not enough bytes in the array");

       assembly {
           // Loop _count times over the array
           for { let i := 0} lt(i, _count) { i := add(i, 1) } { 
               // Make use of mstore8 (1 byte) instead of mstore (32 bytes)
               mstore8(add(bytesTest, i), 0x33)
           }
       }

       return bytesTest[0];
   }
}

再加上第三個例子,它不依賴於solidity數組,而是通過彙編直接在記憶體中分配/計算。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TestAssembly {
   function test(uint8 _count) public pure returns (bytes32) {

       bytes32 result;

       // Protect against buffer overflow
       require(_count <= 32, "not enough bytes in the array");

       assembly {
           
           // Allocate 32 bytes from the free memory pointer
           let buffer := mload(0x40)

           // Increase the free memory pointer to account for our buffer
           mstore(0x40, add(buffer, 0x20))

           // Loop _count times over the array
           for { let i := 0} lt(i, _count) { i := add(i, 1) } { 
               // Make use of mstore8 (1 byte) instead of mstore (32 bytes)
               mstore8(add(buffer, i), 0x33)
           }

           result := mload(buffer)

           // Decrease the free memory pointer to account for our buffer
           mstore(0x40, sub(buffer, 0x20))
       }

       return result;
   }
}

引用自:https://ethereum.stackexchange.com/questions/120723