如何控制if跳出_Wasm介绍之5:控制指令 | 火星技术帖
免责声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。
小编:记得关注哦
来源:CoinEx公链Talk
WebAssembly(简称Wasm)控制指令一共有11条,其中unreachable
指令(操作码0x00
)和nop
指令(操作码0x01
)比较简单,不介绍。call
指令(操作码0x10
)已经在上一篇文章里介绍,call_indirect
指令(操作码0x11
)将在下一篇文章里介绍。本文重点讨论block
(操作码0x02
)、loop
(操作码0x03
)、if
(操作码0x04
)、br
(操作码0x0C
)、br_if
(操作码0x0D
)、br_table
(操作码0x0E
)和return
(操作码0x0F
)这7条指令。
block
block
指令相当于一个无参的内联(inline)函数调用。函数的返回值类型,也就是block
指令的结果类型(Result Type,在后面的示意图中简称rt
)编码后存储在指令的第一个立即数参数里。函数的指令(可能有很多条)编码后存储在第二个立即数参数里。block
指令必须以end
指令(操作码0x0B
)结尾。由于end
指令和后面将要介绍的else
指令(操作码0x05
)只起到标记作用,没有任何执行效果,所以没有把这两条指令计入控制指令。
Wasm1.0规范规定block
指令的结果不能超过一个,所以rt
可以用一个字节表示:0x40
表示没有结果、0x7F
表示i32
类型、0x7E
表示i64
类型、0x7D
表示f32
类型、0x7C
表示f64
类型。根据讨论可知,block
指令在执行时不会使用栈上已经存在的任何操作数,执行完毕后可能会在栈顶留下一个操作数,下面是它的示意图:
bytecode:...][ block ][ rt ][ instrs ][ end ][...stack:| | | | | | ➘| ?(rt) | # exec(instrs)| d | | d | | c | | c | | b | | b | | a | | a | └───────────┘ └───────────┘
下面是一个非常简单的WAT例子,展示了block
指令的用法:
(module (func (result i32) ;; ... other instructions (block (result i32) (i32.const 100) ) ))
loop
loop
指令和block
指令非常相似,区别仅在于如何跳出控制块。后文介绍br
指令时会进一步讨论这个区别,下面先给出一个跳转示意图:
...][ block ][ rt ]...[ br ]...[ end ][... | ↑ └────────┘...][ loop ][ rt ]...[ br ]...[ end ][... ↑ | └───────────────┘
if
和block
指令类似,if
指令也类似于一个内联函数。区别主要有两点。第一,if
内联函数带一个i32
类型的参数。第二,if
内联函数带有两份代码(两条分支),中间用else
指令隔开。if
指令执行时,会先从栈顶弹出这个i32
类型的参数,如果参数值不等于0,则执行分支1代码,否则执行分支2代码。下面是if
指令的示意图:
bytecode:...][ if ][ rt ][ instrs1 ][ else ][ instrs2 ][ end ][...stack:| | | | | e(i32) |➚ ➘| ?(rt) | # exec(e!=0?instrs1:instrs2)| d | | d || c | | c | | b | | b | | a | | a | └───────────┘ └───────────┘
也可以把if
指令的else
分支省略,但是这种情况下if
指令不能有任何结果。下面是省略else
分支时if
指令的示意图:
bytecode:...][ if ][ 0x40 ][ instrs1 ][ end ][...stack:| | | | | e(i32) |➚ | | # e==1?exec(instrs1)| d | | d || c | | c | | b | | b | | a | | a | └───────────┘ └───────────┘
下面这个WAT例子展示了如何用if
指令实现max
函数:
(module (func $max (param $a i32) (param $b i32) (result i32) (i32.gt_s (local.get $a) (local.get $b)) (if (result i32) (then (local.get $a)) (else (local.get $b)) ) ))
br
br
指令(可以理解为break,或者branch)可以进行无条件跳转。和传统汇编语言里的JUMP
指令不同,br
指令并不能跳转到任意位置,而只能跳出(相对于block
和if
指令而言是跳出,相对于loop
指令而言是重新开始,后面不再强调)其他控制指令产生的控制块。br
指令带有一个u32
类型(32位无符号整数)的立即数参数,指定跳转的层数:0表示跳出当前循环,1代表跳出2层循环,以此类推。下面是一个WAT例子,展示了嵌套的block
,以及br
指令的用法:
(module (func (export "main") (result i32) (i32.const 100) (block (result i32) (i32.const 200) (block (result i32) (i32.const 300) (block (result i32) (i32.const 123) (br n) ) (i32.add) ) (i32.add) ) (i32.add) ))
假设上面例子中的main
函数已经执行到了br
指令这里,下图展示了跳转层数分别为0、1、2、3时操作数栈的变化情况:
bytecode:...][ br ][ depth ][...stack:| | | | | | | | | || | | | | | | | | || 123 | | 123 | | | | | | || 300 | | 300 | | 123 | | | | || 200 | | 200 | | 200 | | 123 | | || 100 | | 100 | | 100 | | 100 | | 123 |└───────────┘ └───────────┘ └───────────┘ └───────────┘ └───────────┘ (before br) n==0 n==1 n==2 n==3
br_if
br_if
指令从栈顶弹出一个i32
类型的操作数,如果操作数的值为0,则不跳转,否则执行br
逻辑。下面是br_if
指令的示意图:
bytecode:...][ br_if ][ depth ][...stack:| | | | | e(i32) |➚ | | | d | | ? | # e!=0?br(depth)| c | | | | b | | | | a | | | └───────────┘ └───────────┘
下面是一个稍微复杂一些的WAT例子,展示了如何用loop
和br_if
指令实现sum
函数:
(module (func $sum (param $from i32) (param $to i32) (result i32) (local $n i32) (loop $l ;; $n += $from (local.set $n (i32.add (local.get $n) (local.get $from))) ;; $from++ (local.set $from (i32.add (local.get $from) (i32.const 1))) ;; if $from
请注意loop
指令并不会自动循环,必须和br
等跳转指令配合使用。
br_table
不管是br
还是br_if
指令,都只有一个立即数参数,能指定一个跳转深度。br_table
指令打破了这种限制,可以带N+1个立即数参数,指定N+1个跳转深度。br_table
指令执行时,会从栈顶弹出一个i32
类型的操作数n
。如果n
小于或等于N,则按第n
个深度跳转,否则按照最后一个深度跳转。下面是br_table
指令的示意图:
bytecode:...][ br_table ][ labels... ][ default ][...stack:| | | | | n(i32) |➚ | || d | | ? | # d
return
return
指令可以认为是br
指令的特殊形式:直接跳出最外层循环(也就是整个函数)。return
指令没有立即数参数,不画示意图了。下面的WAT例子展示了如何用block
、br_table
和return
指令实现Go等高级语言中的switch-case
语句:
(module (func $select3 (param $n i32) (param i32 i32 i32) (result i32) (block (block (block (local.get $n) (br_table 0 1 2) ) (return (local.get 1)) ) (return (local.get 2)) ) (return (local.get 3)) ))
如果把上面例子中定义的select3
函数翻译成Go语言代码的话,应该是下面这样:
func select3(n, a, b, c int32) int32 { switch n { case 0 : return a case 1 : return b default: return c }}
*本文由CoinEx Chain开发团队成员Chase撰写。CoinEx Chain是全球首条基于Tendermint共识协议和Cosmos SDK开发的DEX专用公链,借助IBC来实现DEX公链、智能合约链、隐私链三条链合一的方式去解决可扩展性(Scalability)、去中心化(Decentralization)、安全性(security)区块链不可能三角的问题,能够高性能的支持数字资产的交易以及基于智能合约的Defi应用。
如何控制if跳出_Wasm介绍之5:控制指令 | 火星技术帖相关推荐
- 模型预测控制(MPC)+逻辑控制(相平面分区控制)--matlab例程介绍
模型预测控制(MPC)+逻辑控制(相平面分区控制)–matlab例程介绍 MATLAB-模型模糊神经网络预测控制demo(训练数据用):链接:https://blog.csdn.net/answerM ...
- windows下编程控制摄像头的详细介绍
这段时间闲来无事,看了看MSDN的文档,自己翻译了一下.一是为了学习,二是对空闲时间的打发.所以也希望大家在拍砖的同时,尊重我的劳动,如要转贴请注明转至blog.csdn.net/suntaoznz. ...
- 论述计算机网络前沿技术,介绍一些计算机网络前沿应用技术
介绍一些计算机网络前沿应用技术 來源:互聯網 2010-05-08 04:22:14 評論 分類: 電腦/網絡 >> 互聯網 問題描述: 我们要写论文,各位请帮帮忙啊.最好详细点,有一 ...
- 今天,正式介绍一下Java极客技术知识星球
前面煽情的文字就不放了,还是那句 别让高手和你距离越来越远,其实你也是高手! 从创建知识星球到现在已经过去一个月的时间了,在这里正式介绍一下 Java极客技术知识星球 星球规划: 一.每周分享一个面 ...
- AIBlockChain:“知名博主独家讲授”人工智能创新应用竞赛【精选实战作品】之《基于计算机视觉、自然语言处理和区块链技术的乘客智能报警系统》案例的界面简介、功能介绍分享之区块链技术
AI&BlockChain:"知名博主独家讲授"人工智能创新应用竞赛[精选实战作品]之<基于计算机视觉.自然语言处理和区块链技术的乘客智能报警系统>案例的界面简 ...
- AIBlockChain:“知名博主独家讲授”人工智能创新应用竞赛【精选实战作品】之《基于计算机视觉、自然语言处理和区块链技术的乘客智能报警系统》案例的界面简介、功能介绍分享之自然语言处理技术
AI&BlockChain:"知名博主独家讲授"人工智能创新应用竞赛[精选实战作品]之<基于计算机视觉.自然语言处理和区块链技术的乘客智能报警系统>案例的界面简 ...
- 权限控制框架Shiro简单介绍及配置实例
Shiro是什么 Apache Shiro是一个非常易用的Java安全框架它能提供验证.授权.加密和Session控制.Shiro非常轻量级而且API也非常易于理解可以使用Shiro完成从APP到企业 ...
- 如何利用状态机编程实现启保停控制(含Stateflow模型介绍)
状态机的介绍这里不再赘述,概念也很简单没有过多的复杂理论.下面我们直接给出具体实现过程.有限自动状态机详细讲解请参看下面的文章链接: PLC面向对象编程系列之有限状态机(FSM)详解_RXXW_Dor ...
- 协同控制笔记1——基础介绍及部分定义定理
一.基础介绍 协同控制主要涉及三个部分: 智能体动力学.智能体间相互作用.协同控制规律 相互作用:智能体通常动力学上彼此解耦.之间的信息交换通常以图的形式表示,可以是静态的(边非时变)或者动态的(边是 ...
最新文章
- linux驱动:音频驱动(六)ASoc之codec设备
- 入门单片机需要购买什么东西,学哪款单片机最好?
- Aix6.1安装openssh
- JSP中javaBean和Servlet理解
- Direct3D 11 Tutorial 4: 3D Spaces_Direct3D 11 教程4:3D空间
- Redis主从配置详细过程
- 南京邮电大学java程序设计作业在线编程第二次作业
- java css是什么_【狂神说JAVA】CSS(通俗易懂版)
- iOS Crash常规跟踪方法及Bugly集成运用
- rancher 启动命令_Rancher 快速上手指南操作(1)
- SWUST大二周赛 之农夫山泉有点甜
- 自然语言处理之维特比(Viterbi)算法
- 【JSP】JSP简单介绍
- 同事写了一个责任链模式,bug无数...
- RabbitMQ特殊应用
- 小学音乐课需要用到的关于《勤快人与懒惰人》的-五线谱
- 运维工程师的宿命(困兽之斗)
- 2022卡塔尔世界杯 | 致我们每个人那份绿茵场上的足球梦
- Django Model用户头像设置
- Python绘制任意正n边形
热门文章
- 腾讯社交广告转化率预估初探
- 零基础轻松学python pdf 小码哥_零基础轻松学Python
- java用for打印正方形_java.java
- php self script name,PHP_SELF,SCRIPT_NAME,REQUEST_URI区别
- 232 Crossword Answers
- kitti数据集简介、百度网盘分享 kitti-object、kitti-tracking 全套数据集 自动驾驶
- odoo中tree视图上面添加按钮并绑定事件
- 第一:MySQL+MyBatis实现对测试用例数据的读取(接口自动化落地)
- excel中如何动态地创建控件以显示查询结果_一起学Excel专业开发02:专家眼中的Excel及其用户...
- [Ext JS 7]7.6 内存泄露及处理