Assembly
這個彙編程式碼如何創建一個新的“記憶體端”?
從文件:
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))
語境:
library GetCode { function at(address _addr) public view returns (bytes memory o_code) { assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(_addr) // allocate output byte array - this could also be done without assembly // by using o_code = new bytes(size) o_code := mload(0x40) // new "memory end" including padding mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // ... } } }
我可以按照運算符解析十六進制,但是我不確定是否應該對基礎值或記憶體地址值本身執行這些操作(例如 0x20 + 0x40 = 0x60)。
它稍後在同一文件中進行了解釋:
Solidity 以一種非常簡單的方式管理記憶體:在記憶體中的 0x40 位置有一個“空閒記憶體指針”。如果要分配記憶體,只需使用從該指針指向的位置開始的記憶體並相應地更新它。
數組總是使用第一個槽來儲存它的長度,並且總是對齊到 32 個字節(一個槽)。
在虛擬碼中,它執行如下操作:
- 讀取空閒記憶體指針
array_memory = memory[0x40]
- 計算記憶體中的數組大小,為數組長度添加額外的 32 字節並將其四捨五入為 32 字節。數學公式是
trunc((code_size + 32 + 32 - 1) / 32) * 32
。並針對 EVM 組裝進行了優化array_size = (code_size + 0x20 + 0x1f) & ~0x1f
- 更新空閒記憶體指針
memory[0x40] += array_size