上一篇文章介绍了WebAssembly(简称Wasm)内存和相关指令,这篇文章将介绍变量指令和函数调用指令。
全局变量
Wasm模块可以定义或者导入全局变量。导入时,可以限定全局变量的类型和可修改性(mutability)。定义时,除了限定类型和可修改性还可以给定初始值。下面是一个WAT例子,展示了全局变量的导入和定义:
(module
(import "env" "g1" (global $g1 i32)) ;; immutable
(import "env" "g2" (global $g2 (mut f32))) ;; mutable
(global $g3 (mut i32) (i32.const 123)) ;; mutable
(global $g4 (mut i64) (i64.const 456)) ;; mutable
(global $g5 f32 (f32.const 1.5)) ;; immutable
(global $g6 f64 (f64.const 2.5)) ;; immutable
(func $main
;; $g3 = $g1
(global.get $g1)
(global.set $g3)
)
)
复制代码
变量指令一共5条,其中2条用来读写全局变量,下面分别介绍。
global.get
global.get0x23global.get
bytecode:
...][ global.get ][ global_idx ][...
stack:
| | | |
| | ➘|globals[i] |
| d | | d |
| c | | c |
| b | | b |
| a | | a |
└───────────┘ └───────────┘
global.set
global.set0x24global.getglobal.set
bytecode:
...][ global.set ][ global_idx ][...
stack:
| | | |
| | | |
| d |➚ | | # globals[global_idx] = d
| c | | c |
| b | | b |
| a | | a |
└───────────┘ └───────────┘
局部变量
全局变量的作用域是整个Wasm模块,局部变量的作用域则是整个函数。下面是一个WAT例子,展示了局部变量的定义和使用:
(module
(func $main (param $a i32) (param $b f32)
(local $c i32)
(local $d i64)
(local $e f32)
(local $f f64)
;; $c = $a
(local.get $a)
(local.set $c)
)
)
从上面的例子可以看到,函数的参数本质上其实就是局部变量。变量指令的其余3条用来读写局部变量,下面分别介绍。
local.get
local.get0x20global.getlocal.get
bytecode:
...][ local.get ][ local_idx ][...
stack:
| | | |
| | ➘| locals[i] |
| d | | d |
| c | | c |
| b | | b |
| a | | a |
└───────────┘ └───────────┘
local.set
local.set0x21global.setlocal.set
bytecode:
...][ local.set ][ local_idx ][...
stack:
| | | |
| | | |
| d |➚ | | # locals[local_idx] = d
| c | | c |
| b | | b |
| a | | a |
└───────────┘ └───────────┘
local.tee
local.tee0x22local.setlocal.teelocal.tee
bytecode:
...][ local.tee ][ local_idx ][...
stack:
| | | |
| | | |
| d |➚ ➘| d | # locals[local_idx] = d
| c | | c |
| b | | b |
| a | | a |
└───────────┘ └───────────┘
函数调用
callcall_indirectcallcall_indirect
call
call0x10calli32i32
bytecode:
...][ call ][ func_idx ][...
stack:
| | | |
| | | |
| d |➚ | |
| c |➚ ➘| r | # funcs[func_idx](c,d)
| b | | b |
| a | | a |
└───────────┘ └───────────┘
calllocal.getlocal.set
(module
(func $main (export "main") (result i32)
(call $max (i32.const 20) (i32.const 80))
)
(func $max (param $a i32) (param $b i32) (result i32)
(local.get $a)
(local.get $b)
(i32.gt_s (local.get $a) (local.get $b))
(select)
)
)
*本文由CoinEx Chain开发团队成员Chase撰写。CoinEx Chain是全球首条基于Tendermint共识协议和Cosmos SDK开发的DEX专用公链,借助IBC来实现DEX公链、智能合约链、隐私链三条链合一的方式去解决可扩展性(Scalability)、去中心化(Decentralization)、安全性(security)区块链不可能三角的问题,能够高性能的支持数字资产的交易以及基于智能合约的Defi应用。