真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么使用SolidityAssembly

這篇文章主要介紹“怎么使用Solidity Assembly”,在日常操作中,相信很多人在怎么使用Solidity Assembly問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么使用Solidity Assembly”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

目前成都創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、茂南網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

1、使用Remix編輯器

首先,讓我們將這個(gè)簡單的合約粘貼到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編輯器。我們首先需要選擇編譯器版本,然后編譯合約、部署合約,執(zhí)行一些功能,然后調(diào)試。

2、第一行匯編代碼

現(xiàn)在,讓我們修改getLength函數(shù)來編寫第一行匯編代碼:

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

上面幾行代碼中發(fā)生了很多事情。匯編就是這樣,要實(shí)現(xiàn)一個(gè)非常簡單的功能也需要很多代碼。我們將testArray從存儲(chǔ)復(fù)制到內(nèi)存,因?yàn)檫@是本文的重點(diǎn)。以后我們可以再談一談存儲(chǔ)插槽。

在深入探討匯編語言塊之前,請注意匯編指令是對32字節(jié)的字進(jìn)行操作。因此,mload指令會(huì)將 memoryTestArray指向的內(nèi)存位置的32個(gè)字節(jié)壓入棧。。

3、Solidity匯編代碼的斷點(diǎn)設(shè)置與單步執(zhí)行

現(xiàn)在調(diào)試一下。在Remix中,你可以通過單擊行號(hào)來設(shè)置一個(gè)斷點(diǎn)。讓我們在第11行上設(shè)置一個(gè)斷點(diǎn),所以它看起來像這樣: 怎么使用Solidity Assembly

更新getLength功能后,請確保已再次編譯并重新部署了合約。現(xiàn)在,讓我們調(diào)用pushElement函數(shù)將字節(jié)0x05插入數(shù)組,然后調(diào)用getLength,該函數(shù)應(yīng)返回1。

調(diào)用getLength后我們可以對其進(jìn)行調(diào)試。在底部面板的最后一個(gè)調(diào)用中單擊“調(diào)試”按鈕,這將在左側(cè)欄中打開調(diào)試器。有一個(gè)用于快進(jìn)的按鈕(如:fast_forward:),它跳到下一個(gè)斷點(diǎn)。讓我們單擊那個(gè)。如果你使用不同的編譯器或不同的設(shè)置,那么對于你來說可能并不完全相同,但是其核心將是相同的。基本的思路是在mload執(zhí)行之前獲取調(diào)試器,在我的環(huán)境中是#0871指令。 怎么使用Solidity Assembly

4、查看Solidity匯編代碼對棧的影響

現(xiàn)在讓我們看一下調(diào)試器側(cè)欄的棧/stack內(nèi)容:

怎么使用Solidity Assembly

在堆棧頂部,位置0處為0x0...80。這是在內(nèi)存中memoryTestArray的位置,該位置將作為mload指令的參數(shù)。

5、查看Solidity匯編代碼對內(nèi)存的影響

現(xiàn)在,讓我們看一下調(diào)試器側(cè)邊欄的“ 內(nèi)存”部分,從地址0x0...80開始:

怎么使用Solidity Assembly

這里有31個(gè)字節(jié)0x00,后跟1個(gè)字節(jié)0x01,然后是1個(gè)字節(jié)0x05,后跟31個(gè)字節(jié)0x00。這可能有點(diǎn)令人困惑,所以讓我們退后一點(diǎn),注意1個(gè)字節(jié)(8位)由2個(gè)十六進(jìn)制數(shù)字表示(1個(gè)十六進(jìn)制數(shù)字表示4位)。同樣,0x10十六進(jìn)制的十進(jìn)制等于16。因此,在內(nèi)存中,位置0x80保存16個(gè)字節(jié),位置0x90(0x80+ 0x10)保存隨后的16個(gè)字節(jié),然后位置0xa0(0x90+ 0x10)保存以下16個(gè)字節(jié),而位置0xb0保存最后的16個(gè)字節(jié)。因?yàn)閰R編中的指令以32字節(jié)為單位操作,所以如果我們調(diào)用mload(0x80),它將從內(nèi)存位置0x80開始取32字節(jié)放入棧。

6、單步執(zhí)行mload指令

讓我們看看實(shí)際執(zhí)行情況。讓我們單擊調(diào)試器中的“單步進(jìn)入”按鈕(即向下的箭頭)來執(zhí)行mload指令。現(xiàn)在看一下棧頂:

怎么使用Solidity Assembly

mload指令取棧頂內(nèi)容:0x0...80,然后將內(nèi)存中位置0x0...1的32個(gè)字節(jié)壓入,這是了解內(nèi)存中的字節(jié)數(shù)組最重要的一點(diǎn):前32個(gè)字節(jié)存儲(chǔ)數(shù)組的長度。

嘗試調(diào)用pushElement函數(shù)將元素0x06插入數(shù)組。然后調(diào)用getLength并再次調(diào)試。同樣,mload將從內(nèi)存位置0x80開始載入32個(gè)字節(jié),但是這次內(nèi)存的內(nèi)容為0x0...2。當(dāng)我們追加新元素時(shí),Solidity為我們更新了數(shù)組的大小。

內(nèi)存中發(fā)生變化的另一件事是,現(xiàn)在位置0xa0是0x050600...00。因此,在內(nèi)存中,一個(gè)字節(jié)數(shù)組變量在前32個(gè)字節(jié)存儲(chǔ)其長度,然后開始存儲(chǔ)具體的成員。首先我們壓入0x05,然后又壓入0x06。

怎么使用Solidity Assembly

7、用Solidity匯編重寫getLength方法

嘗試再壓入一些元素,調(diào)用getLength并調(diào)試,以查看內(nèi)存中的新字節(jié)。如果我們將getElement 轉(zhuǎn)換為匯編,這個(gè)過程將變得更加清晰:

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;
}

好吧,這可能有點(diǎn)嚇到你了!讓我們慢慢地捋一下。

第一件超級(jí)重要的事情是,我們添加了require語句來檢查index并沒有超出范圍。這在調(diào)用mload時(shí)是至關(guān)重要的,我們需要確保要載入的內(nèi)存位置是正確的,否則可能就會(huì)泄漏調(diào)用者不應(yīng)該訪問的信息,這可能會(huì)讓我們的合約存在嚴(yán)重的受攻擊風(fēng)險(xiǎn)。

接下來,讓我們看一下匯編代碼塊。由于mload一次讀取32個(gè)字節(jié),因此僅讀取1個(gè)字節(jié)并不容易。如果我們把index除以32并取整,這將得到要查找的成員所在的32字節(jié)的序號(hào)。例如:

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

看起來還不錯(cuò)。但是請記住,內(nèi)存中memoryTestArray指向的內(nèi)置的第一個(gè)字(32字節(jié))是存儲(chǔ)數(shù)組長度的。因此,我們需要加上32個(gè)字節(jié)來查找第一個(gè)數(shù)組成員。考慮到所有這些因素后,我們就可以載入包含我們需要的1個(gè)字節(jié)的字(32字節(jié)):

memoryTestArray的內(nèi)存位置加上32個(gè)字節(jié)以跳過數(shù)組長度,再加wordIndex上乘以32,因?yàn)槊總€(gè)字都有32個(gè)字節(jié)。

但是還沒有完成?,F(xiàn)在我們需要從這個(gè)字中恰好提取1個(gè)字節(jié)。為此,我們需要在字中找到該字節(jié)的索引。這是字索引除以32的余數(shù)部分,可以通過mod指令獲得。例如:

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

不錯(cuò),下面讓我們完成最后一步,提取該字節(jié)。為了讓字節(jié)在最前面,我們向左移動(dòng)需要的位數(shù)。shl指令一次移動(dòng)一位,所以為了移動(dòng)指定的位數(shù),我們要把indexInWord乘以8。

一旦我們將以這個(gè)字節(jié)開頭的32個(gè)字節(jié)的字賦值給result變量,它就會(huì)刪除所有其他字節(jié),因?yàn)?我們將其類型聲明為bytes1

到此,關(guān)于“怎么使用Solidity Assembly”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!


本文標(biāo)題:怎么使用SolidityAssembly
分享鏈接:http://weahome.cn/article/pscsgj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部