Как и где закончить работу этой программы конечного автомата? - PullRequest
1 голос
/ 07 мая 2019

Я написал эту программу из предоставленной мне схемы. Я просто не могу понять, где и как это остановить. Он постоянно просит вводить данные навсегда. Где добавить команду выхода в моей программе? Есть идеи?

Спасибо.

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

1 Ответ

2 голосов
/ 07 мая 2019

Обычно для конечного автомата вы пишете его как одну функцию, используя jmp вместо call для перехода в следующее состояние.

Ваше состояниефункции никогда не возвращаются, они всегда переходят в новое состояние (или для повторного запуска текущего состояния, например call s1 в нижней части s1.). ret в конце никогда не достигается, поэтому выпросто нажимая постоянно растущее количество адресов возврата, которые мешают вам на самом деле вернуться к main.

Используйте метки типа s1: вместо s1 proc.Или вы все еще можете использовать этот синтаксис MASM, чтобы представить, что каждая из них является отдельной функцией, но использовать jmp s2 для вызова следующего состояния.

Затем, когда вы обнаружите условие завершения в качестве следующего состояния, вы можете ret, и он вернется к main.


Это имеет большое преимущество в том, что вы можете использовать условные ветви, такие как jne s1 вместо того, чтобы перепрыгивать через вызов / jmp .Синтаксис MASM .if может быть недостаточно мощным, чтобы сделать это за вас, но вы все равно получаете огромные пропущенные оптимизации при использовании этого.Например, a==0 && b==0 можно проверить с помощью mov eax, a / or eax, b / jz both_were_zero.Кроме того, имея только 2 «переменные», сохраняйте их в сохраняемых вызовах регистрах, таких как ebx и esi или что-то в этом роде, вместо того, чтобы вообще хранить их в памяти.Вот для чего нужны регистры!Вы пишете в asm

Кроме того, вы можете оптимизировать, выложив их так, чтобы s3 мог провалиться в s1 вместо окончания jmp s1.Или будь проще и держи jmp.(Если бы я выполнял эту оптимизацию, я бы оставил jmp s1 в качестве комментария в качестве документации о том, что переход к s1 в качестве следующего состояния является преднамеренным.)


Остальная часть вашего кода вложена в ваш main proc, что странно , но, возможно, не вызывает реальной проблемы.Но первый блок кода с началом main показывает, что он падает с call waitmsg на myexit proc?Это очень странно, но на самом деле должно работать, если myexit - то, чего вы хотите.

Кроме того, у вас нет строки main endp до конца файла, поэтому вы сообщаетеассемблер, что другие proc декларации находятся внутри main.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...