1

我已经根据给我的图表编写了这个程序。我只是不知道在哪里以及如何阻止它运行。它一直在要求输入。在我的程序中在哪里添加退出命令?任何想法?

谢谢你。

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
4

1 回答 1

2

通常对于状态机,您会将其编写为单个函数,使用jmp而不是call进入下一个状态。

您的状态函数永远不会返回,它们总是跳转到新状态(或重新运行当前状态,如call s1底部的s1。)ret永远不会到达最后,所以您只是在推动不断增长的数量阻止您实际返回的返回地址main

使用类似的标签s1:而不是s1 proc. 或者你仍然可以使用 MASM 语法来假装每个都是单独的函数,但jmp s2用来尾调用下一个状态。

然后当你检测到一个终止条件作为下一个状态时,你可以 ret,它会返回到main


这有一个很大的优势,您可以使用条件分支,jne s1而不是跳过 call/jmp。MASM 的.if语法可能不够强大,无法为您做到这一点,但无论如何您都会因为使用它而错过大量优化。例如a==0 && b==0,可以使用mov eax, a/ or eax, b/进行检查jz both_were_zero。另外,只有 2 个“变量”,将它们保存在调用保留寄存器中,例如ebxesi或其他东西,而不是将它们保存在内存中。这就是寄存器的用途!你在用 asm 写

此外,您可以通过布置它们进行优化,这样s3可以直接进入s1而不是以jmp s1. 或者保持简单并保留jmp. (如果我正在做这个优化,我会留下jmp s1注释作为文档,表明s1下一个状态是有意的。)


您将其余代码嵌套在您的main proc中,这很奇怪,但可能不会导致实际问题。但是以 开头的第一个代码块main显示它从call waitmsginto myexit proc? 这非常奇怪,但如果myexit是你想要发生的事情,它应该真的有效。

此外,在文件末尾之前你没有main endp一行,所以你告诉汇编器其他proc声明在里面main

于 2019-05-07T03:33:41.067 回答