Assembly 如何以及在哪里结束这个有限状态机程序的工作?
我根据给我的图表写了这个程序。我只是不知道在哪里,如何阻止它运行。它永远都在要求投入。在我的程序中的何处添加退出命令?有什么想法吗 多谢各位Assembly 如何以及在哪里结束这个有限状态机程序的工作?,assembly,x86,masm,irvine32,state-diagram,Assembly,X86,Masm,Irvine32,State Diagram,我根据给我的图表写了这个程序。我只是不知道在哪里,如何阻止它运行。它永远都在要求投入。在我的程序中的何处添加退出命令?有什么想法吗 多谢各位 INCLUDE Irvine32.inc .data A DWord ? B dword ? prompta byte "what is your digit a?",0 promptb byte "what is your digit b?",0 message0 byte "you are in s0 with output ",0 message
INCLUDE Irvine32.inc
.data
A DWord ?
B dword ?
prompta byte "what is your digit a?",0
promptb byte "what is your digit b?",0
message0 byte "you are in s0 with output ",0
message1 byte "you are in s1 with output ",0
message2 byte "you are in s2 with output ",0
message3 byte "you are in s3 with output ",0
.code
main PROC
call s0
call waitmsg
初始状态为S0
myexit proc
mov eax, white+16*black
call settextcolor
call waitmsg
ret
myexit endp
这里的退出程序不起作用
readdigits proc
mov edx, offset prompta
call writestring
call readint ; dword into eax
mov a,eax
mov edx, offset promptb
call writestring
call readint
mov b,eax
ret
readdigits endp
S0、S1、S2、S3的程序从这里开始
s0 proc
mov edx,offset message0
call writestring
mov eax,0 ;Output is 0 in State 0
call writedec
call crlf
call readdigits
.if(a==0)&&(b==0)
call s0
.endif
.if(a==1)&&(b==1)
call s1
.endif
call s2
ret
s0 endp
s1 proc
mov edx,offset message1
call writestring
mov eax,0 ;Output is 1 in State 0
call writedec
call crlf
call readdigits
.if(a==0)&&(b==0)
call s2
.endif
.if(a==1)&&(b==1)
call s3
.endif
call s1
ret
s1 endp
s2 proc
mov edx,offset message2
call writestring
mov eax,1 ;Output is 1 in State 2
call writedec
call crlf
call readdigits
.if(a==0)&&(b==0)
call s0
.endif
.if(a==1)&&(b==1)
call s1
.endif
call s2
ret
s2 endp
s3 proc
mov edx,offset message3
call writestring
mov eax,1 ;Output is 1 in State 2
call writedec
call crlf
call readdigits
.if(a==0)&&(b==0)
call s2
.endif
.if(a==1)&&(b==1)
call s0
.endif
call s1
ret
s3 endp
main endp
end main
通常,对于状态机,您可以将其作为单个函数编写,使用
jmp
而不是call
转到下一个状态。
您的状态函数永远不会返回,它们总是跳转到新状态(或重新运行当前状态,如s1
底部的调用s1
),最后的ret
永远不会到达,因此,您只是在推送越来越多的返回地址,阻止您实际返回到main
使用像s1:
这样的标签,而不是s1 proc
。或者您仍然可以使用MASM语法来假装每个函数都是单独的函数,但是使用JMPS2
来跟踪调用下一个状态
然后当您检测到终止条件作为下一个状态时,您可以ret
,它将返回到main
这有一个很大的优势,即您可以使用条件分支,如
jne s1
,而不是跳过调用/jmp。MASM的.if
语法可能不足以为您做到这一点,但无论如何,您都会因为使用它而错过大量优化。e、 g.a==0&&b==0
可通过mov-eax,a
/或eax,b
/jz检查,两者均为零
。另外,只有2个“变量”,将它们保存在调用保留寄存器中,如ebx
和esi
或其他什么,而不是将它们保存在内存中。这就是寄存器的用途!你在用asm写东西
此外,您还可以通过布局进行优化,使s3
可以归入s1
,而不是以jmp s1
结尾。或者保持简单并保持jmp
。(如果我在做这个优化,我会把jmps1
作为注释,作为文档,作为下一个状态是有意的。)
剩下的代码嵌套在
主进程中
,这很奇怪,但可能不会造成实际问题。但是以main
开头的第一个代码块显示它从callwaitmsg
进入myexit proc
?这太奇怪了,但如果myexit
是您希望发生的事情,那么它实际上应该会起作用
另外,直到文件末尾,您才有一行
main endp
,因此您告诉汇编程序,其他proc
声明在main
中(可能与主题无关)。您将剩下的代码嵌套在main
过程中?所以它从callwaitmsg
进入myexit proc
?这太奇怪了,直到文件的末尾才有main endp
行。我认为这并不能解决您的问题,因为我认为您说的是S0
永不返回。您开始使用的图表是否有结束状态?(可以绘制为双圆。)@prl否,图表没有结束状态。