More Related Content Similar to Wasm text (10) Wasm text2. S-表达式
func <signature> <locals> <body>
签名(是声明函数参数与返回值)
局部变量(声明局部变量)
指令列表
举例:(func (param i32) (param i32) (result f64) ... )
Param类型
•i32:32位整数
•i64:64位整数
•f32:32位浮点数
•f64:64位浮点数
3. 参数和局部变量
( func (param $p1 i32) (param $p2 f32) (local $loc f64) )
param local
get_local <index>
get_local <name> push
push
Stack
• 两种命名方式(索引/$名称)
• get_local两种获取参数和局部变量值的方式
• 所谓获取值就是把指定的参数或者局部变量入栈
4. 栈机器
(func (param $p i32)
get_local $p
get_local $p
i32.add) $p
$p
Stack
$p+$p
Stack
get_local把参数入栈
I32.add
• 从栈顶取两个值
• 计算两值之和
• 从栈顶抛栈两次
• 把和入栈
WebAssembly验证规则确保栈准确匹配:如果你声明了
(result f32),那么,最终栈上必须包含一个f32类型值。如
果没有result类型,那么栈必须是空的。
5. WASM导出函数
(module
(func $add
(param $lhs i32) (param $rhs i32) (result i32)
get_local $lhs
get_local $rhs
I32.add
)
(export "add" (func $add))
)
使用函数名/或者根据索引引用函数
result指定返回值类型
函数体
导出函数名 指定哪个函数被导出
6. 同一模块中的函数调用
(module
(func $getAnswer (result i32)
i32.const 42
)
(func (export "getAnswerPlus1") (result i32)
call $getAnswer
i32.const 1
I32.add
)
)
42
1
Stack
栈顶
43
Stack
栈顶
(export "getAnswerPlus1" (func $functionName))
7. 从Javascript中导入函数
(module
(import "console" "log" (func $log (param i32)))
(func (export "logIt")
i32.const 13
call $log)
)
console.log (func $log (param i32))
从javascript中导入console.log
var importObject = {
console: {
log: function(arg) {
console.log(arg);
}
}
};
fetchAndInstantiate('logger.wasm', importObject).then(function(instance)
{ instance.exports.logIt();
});
WASM
在Javascript中使用
13
Stack
1
2
传递给$log的参数是通过
栈传递的
8. var memory = new WebAssembly.Memory({initial:1});
var importObj = {
console: { log: consoleLogString },
js: { mem: memory }
};
fetchAndInstantiate('logger2.wasm', importObject).then(function(instance)
{ instance.exports.writeHi();
});
consoleLogString(offset, length) {
var bytes = new Uint8Array(memory.buffer, offset, length);
var string = newTextDecoder('utf8').decode(bytes);
console.log(string);
}
线性内存
(module
(import "console" "log" (func $log (param i32 i32)))
(import "js" "mem" (memory 1))
(data (i32.const 0) "Hi")
(func (export "writeHi")
i32.const 0 ;; pass offset 0 to log
i32.const 2 ;; pass length 2 to log
call $log)
)
从javascript导入js.mem对象,对应一块内存,
这块内存在js从层通过WebAssembly.Memory
分配,分配大小是1页(其中一页表示64KB)
在data段偏移量0处写入字符串Hi
1
2
3
4
分配内存
根据偏移量和长度,从内存中读取数据
传递内存
9. WebAssembly表格 解决运行时函数运行地址不确定的问题
• C:函数指针
• C++:虚函数
fetchAndInstantiate('wasm-table.wasm').then(function(instance)
{ console.log(instance.exports.callByIndex(0)); // 返回42 console.log(instance.exports.callByIndex(1));
// 返回13 console.log(instance.exports.callByIndex(2)); // 返回一个错误,因为在表格中没有索引值2
});
function() { // table section
var tbl = new WebAssembly.Table(
{initial:2, element:"anyfunc"}
); // function sections:
var f1 = function() { … }
var f2 = function() { … } // elem section
tbl.set(0, f1);
tbl.set(1, f2);
};
Javascript调用
表格实例的Javascript等价实现
10. WebAssembly表格
(module
(table 2 anyfunc)
(func $f1 (result i32) i32.const 42)
(func $f2 (result i32) i32.const 13)
(elem (i32.const 0) $f1 $f2)
(type $return_i32 (func (result i32)))
(func (export "callByIndex") (param $i i32) (result
i32) get_local $i
call_indirect $return_i32)
)
声明一个table,其中有两个item,每个item的类型是anyfunc
声明两个func
使用$f1,$f2两个函数,从i32.const指定的偏移量0处,填充table
定义一个$return_i32的类型,用于类型检查
$i
Stack
$i
Stack
Type check 执行
参数入栈 根据参数到table中索引func 对func进行类型检查
11. WebAssembly表格
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
fetchAndInstantiate('table.wasm').then(function(instance) {
var tbl = instance.exports.tbl;
console.log(tbl.get(0)()); // 13
console.log(tbl.get(1)()); // 42
otherTable.set(0,tbl.get(0));
otherTable.set(1,tbl.get(1));
console.log(otherTable.get(0)());
console.log(otherTable.get(1)());
});
(module
(func $thirteen (result i32) (i32.const 13))
(func $fourtytwo (result i32) (i32.const 42))
(table (export "tbl") anyfunc (elem $thirteen $fourtytwo))
)
•一个模块可以有N个实例,这与一个函数可以产生N个闭包
值一样。
•一个模块实例可以使用0-1个内存实例,它为这个实例提供
了“地址空间”。将来的WebAssembly版本可能允许每个模
块实例拥有0-N个内存实例(参考多表格与内存)。
•一个模块实例可以使用0-1个表格实例——这是该实例的
“函数地址空间”,可以用来实现C函数指针。将来的
WebAssembly版本可能允许每个模块实例拥有0-N个表格
实例。
•一个内存或表格实例能够被0-N个模块实例使用——这些
实例全部共享相同的地址空间,这使得动态链接成为可能。
REFERENCE:
https://developer.mozilla.org/zh-CN/docs/WebAssembly