溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

solidity智能合約[50]-assembly內(nèi)聯(lián)匯編

發(fā)布時間:2020-07-20 12:50:04 來源:網(wǎng)絡 閱讀:681 作者:jonson_jackson 欄目:開發(fā)技術(shù)

內(nèi)聯(lián)匯編

對于普通的solidity智能合約來說,通過solc編譯器的優(yōu)化操作,將源代碼轉(zhuǎn)換為以太坊能夠識別的二進制文件。但是solc編譯器不是萬能的,在某些情況下,例如循環(huán)操作的時候,并不能達到最佳的執(zhí)行方式。通過在solidity智能合約中內(nèi)嵌匯編代碼,可以阻止編譯器的優(yōu)化,在某些時候能夠到達節(jié)約gas的作用。同時,內(nèi)嵌匯編代碼可以增加solidity語言的功能。例如在判斷賬戶地址為合約地址還是外部地址的時候,只能夠通過匯編代碼來實現(xiàn)。

內(nèi)聯(lián)匯編語法

1
2
3
assembly{
 內(nèi)聯(lián)匯編語句
}

將for循環(huán)轉(zhuǎn)換變?yōu)閮?nèi)聯(lián)匯編

let指令定義變量。
add函數(shù)是內(nèi)聯(lián)匯編中內(nèi)置的加法操作,solidity內(nèi)聯(lián)匯編中有很多內(nèi)置的函數(shù)。jumpi為跳轉(zhuǎn)函數(shù),跳轉(zhuǎn)到loop語句執(zhí)行。
It函數(shù)為小于函數(shù),lt(i,9)判斷i是否小于9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function nativeLoop() public returns(uint _r){

    for(uint i = 0;i<10;i++){
        _r += i;
    }
}


function asmloop() public returns(uint _r){

    assembly{

        let i :=0
        loop:
             i:=add(i,1)
             _r := add(_r,i)
             jumpi(loop,lt(i,9))
    }
}

條件語句轉(zhuǎn)換為內(nèi)聯(lián)匯編

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function nativeConditional(uint _v) returns(uint _r){

   if(5==_v){
       _r =  55;
   }
   else if(6 ==_v){
       _r =  66;
   }

   _r =  11;
}

function asmConditional(uint _v) public returns(uint _r){

   assembly{

       switch _v

       case 5{
           _r:=55
       }
       case 6{
              _r:=66
       }
       default{
           _r:=11
       }
   }
}

內(nèi)聯(lián)匯編解析1

下面的合約中,msize()代表的是當前已經(jīng)使用的memory空間的最大位置。加1之后,代表的是可用的指針所在的位置。
mstore代表將值_v賦值給_ptr。 return (ptr,0x20)代表的是從位置_ptr開始,往下讀取0x20也就是32個字節(jié)

1
2
3
4
5
6
7
function asmReturens(uint _v) public returns(uint){
     assembly{
         let _ptr :=add(msize(),1)
         mstore(_ptr,_v)
         return (_ptr,0x20)
     }
 }

內(nèi)聯(lián)匯編解析2

mload(40)代表獲取0x40位置往下32個字節(jié)存儲的數(shù)據(jù)。0x40位置非常特殊,其存儲的是最小的可用的memory內(nèi)存的地址。
例如為0x80.
mstore(add(freemem_pointer,0x00),“36e5236fcd4c610449678014f0d085”) 存儲字符串到"36e5236fcd4c610449678014f0d085" 到0x80往下32個字節(jié)的空間中。
mstore(add(freemem_pointer,0x20),“36e5236fcd4c610449678014f0d086”) 首先將0x80加上32個字節(jié),變?yōu)榱?xa0。之后便加上32個字節(jié),存儲字符串"36e5236fcd4c610449678014f0d086" 到0xa0往下32個字節(jié)的空間中。
let arr1:=mload(freemem_pointer)定義了變量arr1. 獲取freemem_pointer往下32個字節(jié)。由于freemem_pointer當前仍然為0x80,因此arr1的值為字符串"36e5236fcd4c610449678014f0d085"。 最后的語句mstore(add(freemem_pointer,0x40),arr1)。存儲了arr1到0xc0地址往下的32個字節(jié)的空間中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pragma solidity ^0.4.23;

contract cat{

   function test(){

       assembly{
           let freemem_pointer :=mload(0x40) //0x80

           mstore(add(freemem_pointer,0x00),"36e5236fcd4c610449678014f0d085")
           mstore(add(freemem_pointer,0x20),"36e5236fcd4c610449678014f0d086")
           let arr1:=mload(freemem_pointer)
           mstore(add(freemem_pointer,0x40),arr1)
       }
   }
}

內(nèi)聯(lián)匯編解析3

下面的函數(shù),實現(xiàn)了將地址轉(zhuǎn)換為動態(tài)字節(jié)數(shù)組的操作。
let m := mload(0x40)獲取0x40位置往下32個字節(jié)存儲的數(shù)據(jù)。0x40位置非常特殊,其存儲的是最小的可用的memory內(nèi)存的地址。例如為0x80. add(m, 20) 將0x80加上了20個字節(jié)(0x14),到達0x94.
xor為位運算的異或操作。相等為0,不等為1。0x140000000000000000000000000000000000000000的長度為168位,幣地址多了6位。假設地址為0xca35b7d915458ef540ade6068dfe2f44e8fa733c。那么異或之后,變?yōu)榱?x14ca35b7d915458ef540ade6068dfe2f44e8fa733c,一共有21個字節(jié)。填充為32個字節(jié)之后變?yōu)榱?x000000000000000000000014ca35b7d915458ef540ade6068dfe2f44e8fa733c,通過mstore存儲到0x94地址之后的32個字節(jié)中。

在memory空間中
0x80 0x0000000000000000000000000000000000000000000000000000000000000014
0xa0 0xca35b7d915458ef540ade6068dfe2f44e8fa733c000000000000000000000000

從而14代表長度為20個字節(jié)。其后面是地址。將0x80的地址賦值給動態(tài)長度字節(jié)變量b。由于動態(tài)長度字節(jié)數(shù)組首先32個字節(jié)存儲長度,后面存儲內(nèi)容。因此將地址轉(zhuǎn)換為了動態(tài)長度數(shù)組。

1
2
3
4
5
6
7
8
9
10
11
contract dog{

 function toBytes(address a) constant returns (bytes b){
  assembly {
       let m := mload(0x40)
       mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, a))
       mstore(0x40, add(m, 52))
       b := m
  }
}
}
  • 本文鏈接: https://dreamerjonson.com/2018/11/24/solidity-50-assembly/

  • 版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 CC BY 4.0 CN協(xié)議 許可協(xié)議。轉(zhuǎn)載請注明出處!

solidity智能合約[50]-assembly內(nèi)聯(lián)匯編

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI