A beágyazott hurkok optimalizálása # 1

Kezdetben az volt a szó, vagy inkább az ötlet, vagy ... a tervezés.

Amikor egy programot ír, amely kiszámolja a Sudoku keresztrejtvényeket, először is szükség volt rá
ötszörös mélységű, majd kilencszeres beágyazott ciklusokat
ciklusokat. Aztán szükség volt rá
optimalizálás. Különösen azért, mert a végleges változat egy egyszerűsített egyszerűsített algoritmussal (egyrészt) már ... huszonhét éves volt
beágyazott hurkok. Ráadásul Pascal a Borman bácsitól, Turbo Pascal'ya-tól kezdve egészen a Delphiig, az index szerepében egyáltalán nem használhat tömböt. Ie ha a ciklus nagyon mély, például akár 5
padlót, akkor minden egyes melléklethez használja a változót.

Ie a leírási részben például a következőket írjuk:

Var i1, i2, i3, i4, i5. byte;

És a végrehajtási részben:

I1: = 1-től 2-ig
I2: = 1-től 3-ig
I3: = 1-től 4-ig
I4: = 1-től 5-ig
I5: = 1-től 6-ig valamilyen eljárás;

Automatizálni fogjuk ezt az algoritmikus anomáliát. Ezenkívül képzelj el egy szörnyeteg ciklust,
aki 27 csatolással rendelkezik!

Ehhez a tudományos kutatáshoz egy kalapáccsal rendelkező szögek szerepére nincs szükségünk: a Turbo Pascal és a Turbo Debugger for Dos - elég a tető fölött. Ezenkívül szerszámok szükségesek
Tűzifa a közvetlen kezek és a fej formája formájában, minőségi szürke anyaggal (az a képesség, hogy imádkozzunk Istenhez Pascalt a megfelelő kód megírásával legalább is üdvözöljük).

Először is, hogy az adatok önmagukban nem járnak, és az eljárások és funkciók valahol nem unatkoznak,
mindkettő egyesül az OOP zászlaja alatt.

Először is, megtervezzük objektumunkat. De, hogy azonnal világosak legyünk, "felhívjuk" a megfelelő rendszert. Hagyja, hogy a kísérleti nyúl szerepe egy ötös mélységű ciklus legyen:

I [1]: = Dn [1] -hoz Up [1] do
I [2]: = Dn [2] -hoz Up [2] do
I [3]: = Dn [3] -hoz Up [3] do
I [4]: ​​= Dn [4] -hoz Up [4] do
I [5]: = Dn [5] -hoz Up [5] a MainProc;

Melyik pótalkatrészeket a létesítményünkre már most ellopták? Ez az index a változó (egzakt tömeg) i, alsó határa - tömb Dn, és a felső, illetve fel- eljárás MainProc, amely az eljárás többször használt mi ciklusban. Ezen túlmenően, annak a ténynek köszönhető, hogy elég nehéz, hogy dolgozzon ki egy rövid és pontos címet, ezt az eljárást, és hívtuk a megbízó (annál is inkább, mert mindez felhajtás neki és tervezett), amely tükrözi a neve MainProc.

A Turbo Pascalban nyissa meg a könyvtárat, ahol a tárgyunk él, és elment kitalálni, mi van benne.

Itt az objektum leírása:

TLoopRunner = objektum
i, Dn, Up. TByteArray10;
Mélység. byte;
MainProcAddr: Pointer;
ParamsStackIndex: byte;
RunItProcOfs: szó;
CallCodeOfProcToLoopOfs: szó;
Init építő (SomeProcAddr: Pointer;
SomeDepth: byte;
SomeDn, SomeUp: TByteArray10);
Eljárás RunIt; virtuális;
Vége;

Nos, milyen furcsa szavak voltak TByteArray10 és Pointer a mi írásainkban? Könnyű. A típus szakaszban, azaz Típus, a TByteArray10-et tízes tömbként írják le
byte:

TByteArray10 = array [1..10] byte;

Most olyan cselekvésekre van szükségünk, amelyek objektumunkat többdimenziós ciklusba fordítjuk. Először a konstruktorról. Bár nagyrészt egyszerű eljárást lehetett elvégezni, de mivel ezt az eljárást először végre kell hajtani, a tervező státusza is rendelkezik. És a név is szabványos, mint minden társa.
init:

Init szerkesztő (SomeProcAddr: Pointer; SomeDepth:
byte; SomeDn, SomeUp: TByteArray10);

Ezután még egy akció, amelyben a ciklusunk megtalálható. Úgy hívják RunIt-nek, azaz. elvégzésére. Nem lesz a paramétere - nincs rá szükségük, de virtuális lesz, és nem azért, mert divatos, hanem azért, mert egyszerűsíti munkánkat saját tárgyunk újjáéledésével:

Eljárás RunIt; virtuális;

PushParam eljárás (AParamAddr: Pointer; AParamType: TParametersTypes);

By the way, milyen paramétereket lehet átadni az eljárásnak vagy a funkciónak? Annak érdekében, hogy ne merítsük fel agyunkat, felsoroljuk a szabványosokat azáltal, hogy hozzáadjuk a pt előtagot minden névhez (mert TParametersTypes). Ez a felsorolás a könyvtáratípusok szakaszában található:

TParametersTypes = (ptByte, ptShortInt, ptWord, ptInteger, ptLongInt, ptReal, ptString, ptArray);

Egy karakter betűzésével azt mondhatjuk: "Mi terveztük, terveztük és végül megterveztük. ”. Mit kell hozzáadni, kivéve egy egyszerű "igen"?

A megtestesülés folyamatában

Most virágokról bogyókra, azaz megfontoljuk, hogyan valósul meg és működik az egész gazdaság.

Először is a sokrétű ciklusunk teste a RunIt-eljárásban van, amely egyébként, mint minden tisztességes eljárás, az inkarnációk szakaszában íródott le. a szó megvalósítása után. És rögtön észrevehetjük, hogy a virtuális szó virtuálisan elment, és ahelyett, hogy nem kevesebb, mint a mágikus szó összeállító, és a szó helyének helyét az asm szó foglalja el - az eljárás tiszta asma:

Eljárás TLoopRunner.RunIt; szerelő;
Asm
Vége;

Ezen túlmenően, az eljárás lényegében tizenegy (tíz - a beágyazott hurok, és a tizenegyedik -. Kód hívja MainProcAddr főrutin módon, hogy a tíz egyszerűen nincs értelme - azok az azonos típusú, talán az, hogy az árnyalatok az első és a tizedik mutatni. hogyan az átmenet az egyik ciklusban a másikra, ráadásul az első szubrutin, hogy egy pillanatra.), mint korábban azt mondta, rutinokat, és mi is olvassa ezeket a részeket az ügy.

Most nézzük meg a RunIt eljárásunk által kért kódot (egyébként a kódot a debugger Turbo Debuggerből szereztük be):

A kötegből térjen vissza a bp értéke, amely
mentettük az eljárás bejáratánál.

Ha megnézed a következő emeleteket, akkor majdnem ugyanaz a kód lesz látható. Különbségek lesznek az "adalékanyagok" esetében
di regisztrálja, hogy megkapjuk a megfelelő eltolás való hozzáférés a fennmaradó tömb elemei i, Dn és fel. Például a második emeleten ez lesz a 2, 0Ch és 16h szám. Ezenkívül minden más emeleten hosszú visszatéréssel térünk vissza az előzőhöz. retf'om nem, hanem egyszerűen ret'om, mert mindannyian ugyanabban RunIt eljárás, ami azt jelenti, hogy - ugyanazt a kódot szegmensben, ezért kell, hogy menjen vissza változtatni csak az érték ip regiszter és cs ne érintse. Emellett a padlóról való visszatéréshez egy nem emlékezetes visszatérési utasítás kódot kell írni, azaz nem ret, és ennek az utasításnak a kódja db 0C3h. Itt nyilvánvaló, hogy annak a ténynek köszönhető, hogy az eljárás nyilvánították RunIt szerelő, akkor Pascal nevű Turbo véli, minden ret'y hosszú és botokkal
a megfelelő hosszú visszatérési kódot (megnézheted magad megváltoztatva valahol db 0C3h ret).

És egy külön szót a tizedik padlóról. Ha például az első emeleten a második, megyünk a „létra» hívni @@ Loop02_Begin, hogy semmi a tizedik emeleten, így a tizedik mi csak azonnal menjen vissza a kilencedik miatt ret utasítás kód, azaz 0S3h (miután ezt az utasítást két nop'a, azaz a visszatérési kód 3 bájt kap -, amire szüksége van, hogy adja meg ezen a helyen, ha szükséges, az utasításokat hívja a fő rutin, és miért van rá szükség. - alább olvashat).

Ossza meg ezt a cikket barátaival:

Kapcsolódó cikkek