您好,登錄后才能下訂單哦!
對于普通的solidity智能合約來說,通過solc編譯器的優化操作,將源代碼轉換為以太坊能夠識別的二進制文件。但是solc編譯器不是萬能的,在某些情況下,例如循環操作的時候,并不能達到最佳的執行方式。通過在solidity智能合約中內嵌匯編代碼,可以阻止編譯器的優化,在某些時候能夠到達節約gas的作用。同時,內嵌匯編代碼可以增加solidity語言的功能。例如在判斷賬戶地址為合約地址還是外部地址的時候,只能夠通過匯編代碼來實現。
1 | assembly{ |
let指令定義變量。
add函數是內聯匯編中內置的加法操作,solidity內聯匯編中有很多內置的函數。jumpi為跳轉函數,跳轉到loop語句執行。
It函數為小于函數,lt(i,9)判斷i是否小于9
1 | function nativeLoop() public returns(uint _r){ |
1 | function nativeConditional(uint _v) returns(uint _r){ |
下面的合約中,msize()代表的是當前已經使用的memory空間的最大位置。加1之后,代表的是可用的指針所在的位置。
mstore代表將值_v賦值給_ptr。 return (ptr,0x20)代表的是從位置_ptr開始,往下讀取0x20也就是32個字節
1 | function asmReturens(uint _v) public returns(uint){ |
mload(40)代表獲取0x40位置往下32個字節存儲的數據。0x40位置非常特殊,其存儲的是最小的可用的memory內存的地址。
例如為0x80.
mstore(add(freemem_pointer,0x00),“36e5236fcd4c610449678014f0d085”) 存儲字符串到"36e5236fcd4c610449678014f0d085" 到0x80往下32個字節的空間中。
mstore(add(freemem_pointer,0x20),“36e5236fcd4c610449678014f0d086”) 首先將0x80加上32個字節,變為了0xa0。之后便加上32個字節,存儲字符串"36e5236fcd4c610449678014f0d086" 到0xa0往下32個字節的空間中。
let arr1:=mload(freemem_pointer)定義了變量arr1. 獲取freemem_pointer往下32個字節。由于freemem_pointer當前仍然為0x80,因此arr1的值為字符串"36e5236fcd4c610449678014f0d085"。 最后的語句mstore(add(freemem_pointer,0x40),arr1)。存儲了arr1到0xc0地址往下的32個字節的空間中。
1 | pragma solidity ^0.4.23; |
下面的函數,實現了將地址轉換為動態字節數組的操作。
let m := mload(0x40)獲取0x40位置往下32個字節存儲的數據。0x40位置非常特殊,其存儲的是最小的可用的memory內存的地址。例如為0x80. add(m, 20) 將0x80加上了20個字節(0x14),到達0x94.
xor為位運算的異或操作。相等為0,不等為1。0x140000000000000000000000000000000000000000的長度為168位,幣地址多了6位。假設地址為0xca35b7d915458ef540ade6068dfe2f44e8fa733c。那么異或之后,變為了0x14ca35b7d915458ef540ade6068dfe2f44e8fa733c,一共有21個字節。填充為32個字節之后變為了0x000000000000000000000014ca35b7d915458ef540ade6068dfe2f44e8fa733c,通過mstore存儲到0x94地址之后的32個字節中。
在memory空間中
0x80 0x0000000000000000000000000000000000000000000000000000000000000014
0xa0 0xca35b7d915458ef540ade6068dfe2f44e8fa733c000000000000000000000000
從而14代表長度為20個字節。其后面是地址。將0x80的地址賦值給動態長度字節變量b。由于動態長度字節數組首先32個字節存儲長度,后面存儲內容。因此將地址轉換為了動態長度數組。
1 | contract dog{ |
本文鏈接: https://dreamerjonson.com/2018/11/24/solidity-50-assembly/
版權聲明: 本博客所有文章除特別聲明外,均采用 CC BY 4.0 CN協議 許可協議。轉載請注明出處!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。