SlideShare a Scribd company logo
WASM Text
S-表达式
func <signature> <locals> <body>
签名(是声明函数参数与返回值)
局部变量(声明局部变量)
指令列表
举例:(func (param i32) (param i32) (result f64) ... )
Param类型
•i32:32位整数
•i64:64位整数
•f32:32位浮点数
•f64:64位浮点数
参数和局部变量
( func (param $p1 i32) (param $p2 f32) (local $loc f64) )
param local
get_local <index>
get_local <name> push
push
Stack
• 两种命名方式(索引/$名称)
• get_local两种获取参数和局部变量值的方式
• 所谓获取值就是把指定的参数或者局部变量入栈
栈机器
(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类型,那么栈必须是空的。
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指定返回值类型
函数体
导出函数名 指定哪个函数被导出
同一模块中的函数调用
(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))
从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的参数是通过
栈传递的
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
分配内存
根据偏移量和长度,从内存中读取数据
传递内存
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等价实现
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进行类型检查
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

More Related Content

What's hot

Intro to C++ Basic
Intro to C++ BasicIntro to C++ Basic
Intro to C++ Basic
Shih Chi Lin
 
Ptyhon 教學 003 函數
Ptyhon 教學 003 函數Ptyhon 教學 003 函數
Ptyhon 教學 003 函數
信宏 陳
 
nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言
吳錫修 (ShyiShiou Wu)
 
Appendix B 範例
Appendix B 範例Appendix B 範例
Appendix B 範例
hungchiayang1
 
第三章
第三章第三章
第三章
贺 利华
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
dennis zhuang
 
sed -- A programmer's perspective
sed -- A programmer's perspectivesed -- A programmer's perspective
sed -- A programmer's perspective
Li Ding
 
Scala再探
Scala再探Scala再探
Scala再探
afeihehe
 
Ruby 使用手冊 (Part 1)
Ruby 使用手冊 (Part 1)Ruby 使用手冊 (Part 1)
Ruby 使用手冊 (Part 1)
Drake Huang
 
Bash shell script 教學
Bash shell script 教學Bash shell script 教學
Bash shell script 教學
Ming-Sian Lin
 
Ch10 範例
Ch10 範例Ch10 範例
Ch10 範例
hungchiayang1
 
C語言結構與串列
C語言結構與串列 C語言結構與串列
C語言結構與串列
吳錫修 (ShyiShiou Wu)
 
Use Lambdas in Android
Use Lambdas in AndroidUse Lambdas in Android
Use Lambdas in Android
koji lin
 
C語言標準輸出入函式
C語言標準輸出入函式C語言標準輸出入函式
C語言標準輸出入函式
吳錫修 (ShyiShiou Wu)
 
Ch10 教學
Ch10 教學Ch10 教學
Ch10 教學
hungchiayang1
 
Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版
Harvey Zhang
 
Python變數與資料運算
Python變數與資料運算Python變數與資料運算
Python變數與資料運算
吳錫修 (ShyiShiou Wu)
 
5, sed
5, sed5, sed
5, sed
ted-xu
 

What's hot (20)

Intro to C++ Basic
Intro to C++ BasicIntro to C++ Basic
Intro to C++ Basic
 
Ptyhon 教學 003 函數
Ptyhon 教學 003 函數Ptyhon 教學 003 函數
Ptyhon 教學 003 函數
 
nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言nodeMCU IOT教學02 - Lua語言
nodeMCU IOT教學02 - Lua語言
 
Appendix B 範例
Appendix B 範例Appendix B 範例
Appendix B 範例
 
第三章
第三章第三章
第三章
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
 
sed -- A programmer's perspective
sed -- A programmer's perspectivesed -- A programmer's perspective
sed -- A programmer's perspective
 
Ch 8
Ch 8Ch 8
Ch 8
 
Ch5
Ch5Ch5
Ch5
 
Scala再探
Scala再探Scala再探
Scala再探
 
Ruby 使用手冊 (Part 1)
Ruby 使用手冊 (Part 1)Ruby 使用手冊 (Part 1)
Ruby 使用手冊 (Part 1)
 
Bash shell script 教學
Bash shell script 教學Bash shell script 教學
Bash shell script 教學
 
Ch10 範例
Ch10 範例Ch10 範例
Ch10 範例
 
C語言結構與串列
C語言結構與串列 C語言結構與串列
C語言結構與串列
 
Use Lambdas in Android
Use Lambdas in AndroidUse Lambdas in Android
Use Lambdas in Android
 
C語言標準輸出入函式
C語言標準輸出入函式C語言標準輸出入函式
C語言標準輸出入函式
 
Ch10 教學
Ch10 教學Ch10 教學
Ch10 教學
 
Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版Swift编程语言入门教程 中文版
Swift编程语言入门教程 中文版
 
Python變數與資料運算
Python變數與資料運算Python變數與資料運算
Python變數與資料運算
 
5, sed
5, sed5, sed
5, sed
 

Similar to Wasm text

ncuma_函式.pptx
ncuma_函式.pptxncuma_函式.pptx
ncuma_函式.pptx
NCU MCL
 
C語言 第4章 基本輸出與輸入功能
C語言 第4章 基本輸出與輸入功能C語言 第4章 基本輸出與輸入功能
C語言 第4章 基本輸出與輸入功能shademoon
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Justin Lin
 
Ch9 教學
Ch9 教學Ch9 教學
Ch9 教學
hungchiayang1
 
Linux常用命令与工具简介
Linux常用命令与工具简介Linux常用命令与工具简介
Linux常用命令与工具简介weihe
 
第4章函数
第4章函数第4章函数
第4章函数
summerfeng
 
Ppt 120-126
Ppt 120-126Ppt 120-126
Ppt 120-126
hungchiayang1
 
ch13-pv1-system-calls
ch13-pv1-system-callsch13-pv1-system-calls
ch13-pv1-system-callsyushiang fu
 
Ppt 120-126
Ppt 120-126Ppt 120-126
Ppt 120-126
hungchiayang1
 

Similar to Wasm text (10)

ncuma_函式.pptx
ncuma_函式.pptxncuma_函式.pptx
ncuma_函式.pptx
 
C語言 第4章 基本輸出與輸入功能
C語言 第4章 基本輸出與輸入功能C語言 第4章 基本輸出與輸入功能
C語言 第4章 基本輸出與輸入功能
 
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
 
Ch9 教學
Ch9 教學Ch9 教學
Ch9 教學
 
Linux常用命令与工具简介
Linux常用命令与工具简介Linux常用命令与工具简介
Linux常用命令与工具简介
 
Cch2v6
Cch2v6Cch2v6
Cch2v6
 
第4章函数
第4章函数第4章函数
第4章函数
 
Ppt 120-126
Ppt 120-126Ppt 120-126
Ppt 120-126
 
ch13-pv1-system-calls
ch13-pv1-system-callsch13-pv1-system-calls
ch13-pv1-system-calls
 
Ppt 120-126
Ppt 120-126Ppt 120-126
Ppt 120-126
 

Wasm text

  • 2. 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