Jak realizovat cyklus FOR ?

Pro potřeby inicializace např. zásobníku je v některých případech nutné realizovat ekvivalent příkazu FOR např. z jazyka C

envelope Popis problému:

V některých případech, zvláště při počáteční inicializaci nebo zápisu inicializačních hodnot je nezbytné tyto hodnoty kopírovat z kódové paměti automatu. V případech kdy je třeba kopírovat pole hodnot je vcelku výhodné použít ekvivalent příkazu FOR např. z jazyka C. Tento příkaz realizuje cyklus, který je dán počáteční hodnotou, koncovou hodnotou proměnné index a hodnotou o níž se proměnná indexu zvětšuje každým průchodem smyčky.

icon_question Jaká jsou omezení dotyčného řešení:

Omezení popisovaného řešení vycházejí z principu programování automatů Micropel. Program by měl inicializovat všechny nezbytné části v okamžiku, kdy je nastaven bit reset. To znamená, že i ekvivalent příkazu FOR musí tuto podmínku respektovat a musí považovat průchody s nastavenou proměnnou reset za inicializační. Na druhou stranu je ale možné bit reset využít k inicializaci vnitřních a pomocných proměnných pro realizaci tohoto příkazu. Druhé omezení spočívá v tom, že musíme respektovat opatrnou práci s proměnnou index, kterou nastavujeme pro spuštění cyklu a současně ji modifikuje ekvivalent příkazu FOR. S touto manipulací souvisí i to, že musíme mít pro každé použití cyklu FOR deklarovanou separátní proměnnou index.

lightbulb Řešení:

pro verzi StudioWin 7.400 a vyšší

Příkaz FOR budeme realizovat jako funkci pro případ indexu typu word podle následující deklarace:

function bit for(var word index, word od, word do)

Funkce bude vracet hodnotu (1) TRUE tehdy, pokud bude cyklus spuštěn, hodnotu 0 (FALSE) pokud cyklus doběhl nebo pokud dochází k inicializaci v důsledku nastaveného bitu reset. Dále nebudeme pro jednoduchost uvažovat obecný krok modifikace proměnné index, ale budeme používat krok s jednotkovou velikostí. Tělo funkce FORbude vypadat takto:

function bit for(var word index, word od, word do)
var bit bezi  ; pomocný bit pro řízení stavu cyklu for při rozběhu
if reset then begin
bezi = 0  ; v případě že je reset, ukončí se funkce
index = od ; inicializace indexu
exit 0
end
if index > do then begin
exit; nebo index je > než do, ukončí se funkce
end
if index = od and bezi = 0 then
begin
bezi =; pokud je index = od,
; tj. inicializační hodnota
exit 1    ; pak se tato hodnota nemění
; a cyklus se rozběhne
end
index = index + 1
bezi = 0   ; první průchod cyklem proběhl
if index <= do then
begin
exit 1   ; cyklus běží
end
return 0 ; cyklus ukončen

Jak je zřejmé ze zdrojového textu, funguje funkce FOR i pro takzvané předčasné ukončení cyklu tím, že nastavíme index na hodnotu větší než je mez do. Tak ukončíme cyklus nezávisle na počtu provedených kroků.

wink_smile Použití:

Použití funkce FOR v programu je pak již jednoduché. Uveďme příklad kopírování 10 wordů z kódové paměti na zásobník od pozice 1000.

code word hodnoty[10]  = (0,1,2,3,4,5,6,7,8,9)
var word index
const od = 0
const do = 9
const stack_zacatek = 1000
if for(index,od,do) then
begin
pointer = stack_zacatek + index
Stack(hodnoty[index]) ; index se inicializuje unvitř
; funkce for v okamžiku kdy reset = 1
exit ; cyklus neskončil a proto ukončíme vykonávání
end   ; hlavní smyčky
; do tohoto mista prijde program nejprve při reset = 1,
; a pak až po deseti průchodech cyklem for
; další program
reset  = 0
end

Jak je vidět z uvedeného zdrojového kódu, příkaz FOR je možné umístit v kódu vícekrát, aniž by to způsobilo nějaký problém. Pokud bychom chtěli vykonávat cyklus FOR jako součást programu a ne pouze jako inicializaci, je nutné po dosažení konce programu inicializovat všechny použité proměnné index. Situaci ukazuje následující kód

; index první smyčky
var word index_0
const od_0 = 0
const do_0 = 18
; index druhé smyčky
var word index_1
const od_1 = 10
const do_1 = 28
; první smyčka
if for(index_0,od_0,do_0 ) then begin
; kód první smyčky for
exit
end
; pokračování programu
; druhá smyčka
if for(index_1,od_1,do_1 ) then begin
; kód druhé smyčky for
exit
end
; dokončení programu
index_0 = od_0
index_1 = od_1
reset = 0
end

Je zřejmé, že meze pro cyklus nemusí být pouze konstanty. Můžeme předávat samozřejmě i proměnné, nicméně musíme dávat dobrý pozor na jejich inicializaci. Jakmile totiž vynulujeme bit reset, cykly FOR začnou nemilosrdně běžet a inicializace mezí je pak problematická. V případě, že používáme pro meze proměnné, je vhodné provést jejich inicializaci hned na začátku kódu v klasické podmínce if reset then....