Конечный автомат — процедура, которая помнит свое состояние и при обращении к ней выполняет различные действия для разных состояний. Например, рассмотрим процедуру, которая складывает регистры АХ и ВХ при первом вызове, вычитает при втором, умножает при третьем, делит при четвертом, снова складывает при пятом и т.д. Очевидная реализация, опять же, состоит в последовательности условных переходов:
state db 0 state_machine: cmp state,0 jne not_0 ; состояние 0: сложение add ax,bx inc state ret not_0: cmp state,1 jne not_1 ; состояние 1: вычитание sub ax,bx inc state ret not_1: cmp state,2 jne not_2 ; состояние 2: умножение push dx mul bx pop dx inc state ret : состояние 3: деление not_2: push dx xor dx,dx div bx pop dx mov state,0 ret
Оказывается, что, как и для CASE, в ассемблере есть средства для более эффективной реализации этой структуры. Это все тот же косвенный переход, использованный нами только что для CASE:
state dw offset state_0 state_machine: jmp state
state_0: add ax,bx ; состояние 0: сложение mov state,offset state_1 ret state_1: sub ax,bx ; состояние 1: вычитание mov state,offset state_2 ret state_2: push dx ; состояние 2: умножение mul bx pop dx mov state,offset state_3 ret state_3: push dx ; состояние З: деление xor dx,dx div bx рор dx mov state,offset state_0 ret
Как и в случае с CASE, использование косвенного перехода приводит к тому, что не требуется никаких проверок и время выполнения управляющей структуры остается одним и тем же для четырех или четырех тысяч состояний.