关于matlab实现有限状态机,有限状态机(FSM)与汇编语⾔
[附带实例]
有限状态机(FSM)是⼀个根据输⼊改变状态的机器或程序。⽤图表⽰ FSM 相当简明, 下图中的矩形(或圆形)称为节点,节点之间带箭头的线段称为边(或弧)。
上图给出了⼀个简单的例⼦。每个节点代表⼀个程序状态,每个边代表从⼀个状态到另⼀个状态的转换。⼀个节点被指定为初始状态,在图中⽤⼀个输⼊箭头指出。其余的状态可以⽤数字或字母来标⽰。⼀个或多个状态可以指定为终⽌状态,⽤粗框矩形表⽰。终⽌状态表⽰程序⽆出错的结束状态。
FSM 是⼀种被称为有向图的更⼀般结构的特例。有向图就是⼀组节点,它们⽤具有特定⽅向的边进⾏连接。
验证输⼊字符串
读取输⼊流的程序往往要通过执⾏⼀定量的错误检查来验证它们的输⼊。⽐如,编程语⾔编译器可以⽤ FSM 来扫描程序,将⽂字和符号转换为记号(通常是指关键字、算法运算符和标识符)。
⽤ FSM 来验证输⼊字符串时,常常是按字符进⾏读取。每⼀个字符都⽤图中的⼀条边(转换)来表⽰。FSM 有两种⽅法检测⾮法输⼊序列:
下⼀个输⼊字符没有对应到当前状态的任何⼀个转换。
输⼊已经终⽌,但是当前状态是⾮终⽌状态。
字符串⽰例现在根据下⾯两条原则来验证⼀个输⼊字符串:
该字符串必须以字母“x”开始,以字母“z”结束。
第⼀个和最后⼀个字符之间可以有零个或多个字母,但其范围必须是 {a,....,y}。
下图的 FSM 显⽰了上述语法。每⼀个转换都是由特定类型的输⼊来标识。⽐如,仅当从输⼊流中读取字母 x 时,才能完成状态 A 到状态B 的转换。输⼊任何⾮“z”的字母,都会使得状态 B 转换为其⾃⾝。⽽仅当从输⼊流中读取字母 z 时,才会发⽣状态 B 到状态 C 的转换。
如果输⼊流已经结束,⽽程序只出现了状态 A 和状态 B,那么就⽣成出错条件,因为只有状态 C 才能标记终⽌状态。下述输⼊字符串能被该 FSM 认可:
xaabcdefgz
xz
xyyqqrrstuvz
验证有符号整数
下图表⽰的是 FSM 解析⼀个有符号整数。输⼊包括⼀个可选的前置符号,其后跟⼀串数字。图中没有对数字个数进⾏限制。
有限状态机很容易转换为汇编代码。图中的每个状态(A、B、C…)代表了⼀段有标号的程序。每个标号执⾏的操作如下:
1) 调⽤输⼊程序读⼊下⼀个输⼊字符。
2)    如果是终⽌状态,则检查⽤户是否按下 Enter 键来结束输⼊。
3)    ⼀个或多个⽐较指令检查从状态发岀的所有可能的转换。每个⽐较指令后⾯跟⼀个条件跳转指令。
⽐如,在状态 A,如下代码读取下⼀个输⼊字符并检查到状态 B 的可能的转换:
StateA:
Cal1 Getnext ;读取下⼀个字符,并送⼊ AL
cmp al, '+' ;前置+ ?
je StateB ;到状态 b
cmp al, '-' ;前置 - ?
je StateB ;到状态 B
call IsDigit ;如果 AL 包含数字,则 ZF = 1
jz StateC ;到状态 C
call DisplayErrorMsg ;发现⾮法输⼊
jmp Quit
下⾯来更详细地检查这段代码。⾸先,代码调⽤ Getnext,从控制台输⼊读取下⼀个字符,送⼊ AL 寄存器。接着检查前置 + 或 -,先将AL 的值与符号“+”进⾏⽐较,如果匹配,就发⽣到标号 StateB 的跳转:
StateA:
call Getnext ;读取下⼀个字符,并送⼊ al
cmp al, ' + ' ;前置 + ?
je StateB ;到状态 B
现在,再次查看上图,发现只有输⼊ + 或 - 时,才发⽣状态 A 到状态 B 的转换。所以,代码还需检查减号:
cmp al, '-' ;前置 - ?
je StateB ;到状态 B
如果⽆法发⽣到状态 B 的转换,就可以检查 AL 寄存器中是否为数字,这可以导致到状态 C 的转换。调⽤ IsDigit ⼦程序,当 AL 包含数字时,零标志位置 1:
call IsDigit ;如果AL包含数字,贝U ZF=1
jz StateC ;到状态 C
最后,状态 A 没有其他可能的转换。如果发现 AL 中的字符既不是前置符号,⼜不是数字,程序就会调
⽤ DisplayErrorMsg (在控制台上显⽰⼀条错误消息)⼦程序,并跳转到标号 Quit 处:
call DisplayErrorMsg ;发现⾮法输⼊
jmp Quit
标号 Quit 标识程序的出⼝,位于主程序的结尾:
Quit:
call Crlf
exit
main ENDP
完整的有限状态机程序
如下程序实现上图所⽰的有符号整数 FSM:
; 有限状态机 (Finite.asm)
INCLUDE Irvine32.inc
ENTER_KEY = 13
.data
InvalidInputMsg BYTE "Invalid input",13,10,0
.code
main PROC
call Clrscr
StateA:
call Getnext ; 读取下⼀个字符,并送⼊AL
cmp al,'+' ; 前置+ ?
je StateB ; 到状态 B
cmp al,'-' ; 前置 - ?
je StateB ; 到状态 B
call IsDigit ; 如果 AL 包含数字 ,则 ZF = 1
jz StateC ; 到状态 C
call DisplayErrorMsg ; 发现⾮法输⼊
jmp Quit
StateB:
call Getnext ; 读取下⼀个字符,并送⼊AL
call IsDigit ; 如果AL包含数字,则 ZF = 1
jz StateC
call DisplayErrorMsg ; 发现⾮法输⼊
jmp Quit
StateC:
call Getnext ; 读取下⼀个字符,并送⼊AL call IsDigit ; 如果AL包含数字,则 ZF = 1 jz StateC
cmp al,ENTER_KEY ; 按下Enter键?
je Quit ; 是:Quit
call DisplayErrorMsg ; 否: 发现⾮法输⼊jmp Quit
Quit:
call Crlf
exit
main ENDP
;-----------------------------------------------Getnext PROC
;
; 从标准输⼊读取⼀个字符
; 接收: ⽆
; 返回: 字符保存在AL中
;-----------------------------------------------call ReadChar ; 从键盘输⼊
call WriteChar ; 显⽰在屏幕上
ret
Getnext ENDP
;-----------------------------------------------DisplayErrorMsg PROC
;
; 显⽰⼀个错误消息以表⽰
; 输⼊流中包含⾮法输⼊
; 接收: ⽆.
; 返回: ⽆
;-----------------------------------------------push edx
mov edx,OFFSET InvalidInputMsg
call WriteString
pop edx
ret
DisplayErrorMsg ENDP
END main
IsDigit⼦程序
有限状态机⽰例程序调⽤ IsDigit ⼦程序,该⼦程序属于本教程的链接库。现在来看看 IsDigit 的源程序,程序把 AL 寄存器作为输⼊,其返回值设置零标志位:
;----------------------------------------------------
IsDigit PROC
;
;确定 AL 中的字符是否为有效的⼗进制数字。
;接收:AL= 字符
;返回:若 AL 为有效的⼗进制字符,ZF=1;否则,ZF=0
;---------------------------------------------------
cmp al,'0'
jb ID1 ;跳转发⽣,ZF=0
cmp al, '9'
ja ID1 ;跳转发⽣,ZF = 0
test ax, 0 ;设置 ZF=1
ID1: ret
IsDigit ENDP
在查看 IsDigit 的代码之前,先回顾⼗进制数字的⼗六进制 ASCII 码,如下表所⽰。由于这些值是连续的,因此,只需要检查第⼀个和最后⼀个值:
字符
'0'
'1'调用子程序的例子
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。