6. PŘESUNY A ARITMETICKÉ PŘÍKAZY 6.1. Příkaz MOVE - - | položka | | literál | Formát: MOVE < figurativní-konstanta > TO položka ... | ALL-klauzule | | podmínkové-jméno | - - Žádná z uvedených položek nesmí mít USAGE INDEX. Funkce: Příkaz MOVE přesunuje vysílající údaj (uvedený za slovem MOVE) do jedné nebo více příjmových položek (uvedených za slovem TO). Tabulka 13 ukazuje, které typy přesunů jsou povolené a které zakázané, a jak se který typ přesunu provádí. Tabulka 13: Povolené typy přesunů. ------------------------------------------------------------ | . příjmová položka |skupin. | | | | . |položka | | | | . | |alfanum.| | | . |alfanum.|editov. |numeric.| | vysílající údaj . |položka |položka |položka | |-------------------------------|--------|--------|--------| |skupinová-položka | AN | AN | AN | |-------------------------------|--------|--------|--------| |alfanumerická-položka | | | | |alfanumerická-editovaná-položka| | | | |numerická-položka | | | | |alf.lit. obsahující jen cifry | AN | AE | NU | |ALL alf.lit. obsah. jen cifry | | | | |numerický-literál | | | | |ZERO, -S, -ES | | | | |-------------------------------|--------|--------|--------| |alf.lit. neobsahující jen cifry| | | | |ALL alf.lit. neobsah. jen cifry| | | | |SPACE, -S | | | | |QUOTE, -S | AN | AE | - | |LOW-VALUE, -S | | | | |HIGH-VALUE, -S | | | | ------------------------------------------------------------ AN ... provádí se alfanumerický přesun AE ... provádí se alfanumerický přesun s edicí NU ... provádí se numerický přesun - ... tento typ přesunu není přípustný Alfanumerický přesun (AN) Alfanumerický přesun se provádí tehdy, když příjmová položka je skupinová nebo alfanumerická anebo když vysílající položka je skupinová (nezávisle na typu příjmové položky). Pravidla: 1) Skupinová položka se do položky jakéhokoliv typu přesunuje alfanumericky přesně stejně, jako kdyby místo příjmové položky stála alfanumerická položka se stejnou délkou. Obsah vysílající skupinové položky se přesunuje bez jakékoliv změny, úpravy nebo edice. 2) Numerická položka se do skupinové položky přesunuje beze změny, jako kdyby místo této numerické položky stála alfanumerická položka se stejnou délkou a se stejným obsahem. Totéž platí i pro přesun exponenciální položky (krátké, dlouhé nebo znakové) nebo numerické editované položky do alfanumerické položky. Numerická položka s pevnou řádovou tečkou se však při přesunu do alfanumerické položky nejprve převede do rozpakovaného tvaru o témže počtu dekadických cifer a vytvoří se její absolutní hodnota (tj. znaménkový půlbyte se změní na hexadecimální 3); pak se provede alfanumerický přesun do příjmové položky. Z důvodu kompatibility i srozumitelnosti programu však doporučujeme tento typ přesunu nepoužívat. 3) Alfanumerická editovaná položka se do skupinové nebo do alfanumerické položky přesunuje alfanumericky přesně stejně, jako kdyby místo ní stála alfanumerická položka se stejnou délkou a se stejným obsahem (žádné "rozeditování" vysílající alfanumerické editované položky se neprovádí). 4) Numerický literál se pro účely přesunu do skupinové nebo alfanumerické položky upraví takto: znaménko, desetinná tečka a exponentová část se vynechají, literál se uloží znakově, přičemž znaménko + resp. - způsobí změnu levého půlbytu u posledního bytu na hexadecimální 3 resp. 4. (Praktický význam má jedině použití celého čísla, které tedy při přesunu do skupinové nebo do alfanumerické položky nemusí být uvedeno v apostrofech.) 5) Je-li vysílajícím údajem figurativní konstanta nebo ALL 'znak', vyplní se celá příjmová položka příslušným znakem. 6) Je-li vysílajícím údajem ALL alfanumerický-literál o délce alespoň dva byty, vyplní se celá příjmová položka cyklicky tímto alfanumerickým literálem, a to: a) pokud příjmová položka nemá klauzuli JUST, pak zleva doprava (první znak literálu přijde na první byte položky); b) pokud příjmová položka má klauzuli JUST, pak zprava doleva (poslední znak literálu přijde na poslední byte položky). 7) Nechť vysílajícím údajem je položka nebo literál; označme v jeho délku (počet bytů). Dále označme p délku (počet bytů) příjmové položky. a) Nechť příjmová položka nemá v popisu klauzuli JUST: - Při v ň p se prvních p bytů vysílajícího údaje (zleva) přesune do příjmové položky; posledních v-p bytů vysílajícího údaje se neuplatní. - Při v < p se na začátek příjmové položky (tj. zleva) přesune všech v bytů vysílajícího údaje a za ně vpravo se přidá p-v mezer. b) Nechť příjmová položka má v popisu klauzuli JUST: - Při v ň p se posledních p bytů vysílajícího údaje (zprava) přesune do příjmové položky; prvních v-p bytů vysílajícího údaje se neuplatní. - Při v < p se na konec příjmové položky (tj. zprava) přesune všech v bytů vysílajícího údaje a před ně vlevo se doplní p-v mezer. Příklad: 02 A PIC X(6). 02 B PIC X(6) JUST. Příkazy "MOVE údaj TO A" a "MOVE údaj TO B" způsobí následující obsazení položek A a B: údaj A (znakově) B (znakově) --------------------------------------------------------- 'ABCDEF' ABCDEF ABCDEF 'ABCD' ABCDbb bbABCD 'ABCDEFGH' ABCDEF CDEFGH 12345 12345b b12345 -12.345E+8 1234Eb b1234E ZERO 000000 000000 ALL 'T' TTTTTT TTTTTT ALL 'ABCD' ABCDAB CDABCD ALL '12' 121212 121212 Příklad: 01 PA PIC S999V9 COMP-3 VALUE -123.4. 01 GR. 02 AN PIC X(6). Přesun "MOVE PA TO GR" se provádí alfanumericky beze změny, takže položka GR získá obsah hexadecimálně 012344202020. Přesun "MOVE PA TO AN" se však provádí tak, že hodnota položky PA se nejdříve převede do rozpakovaného tvaru bez znaménka, takže položka AN získá obsah znakově 1234bb (hexadecimálně 313233342020). Alfanumerický přesun s edicí (AE) Alfanumerický přesun s edicí se provádí tehdy, když příjmová položka je alfanumerická editovaná a vysílající údaj je libovolný s výjimkou skupinové položky. Přesun si lze představit rozdělen do těchto dvou kroků (které se ovšem ve skutečnosti provádějí současně a žádná "fiktivní alfanumerická položka" neexistuje): 1) Nejprve se alfanumericky (AN) přesune vysílající údaj do fiktivní alfanumerické položky, která má právě takovou délku, kolik znaků X, A a 9 obsahuje vzor v klauzuli PICTURE u příjmové alfanumerické editované položky, a která má klauzuli JUST právě tehdy, když příjmová alfanumerická editovaná položka má klauzuli JUST. 2) Nyní se tato fiktivní alfanumerická položka přesune do příjmové alfanumerické editované položky tak, že se umístí jednotlivé byty fiktivní alfanumerické položky po řadě na ty byty příjmové položky, jimž ve vzoru odpovídá znak X nebo A nebo 9, a vloží se mezera resp. nula resp. lomítko resp. znak "x" na ty byty příjmové položky, jimž ve vzoru odpovídá znak B resp. 0 resp. / resp. dvojznak Yx. Příklad: 02 A PIC XX0XBX/XXB0. 02 B PIC XX0XBX/XXB0 JUST. Příkazy "MOVE údaj TO A" a "MOVE údaj TO B" způsobí následující obsazení položek A a B: údaj A (znakově) B (znakově) --------------------------------------------------- 'ABCDEF' AB0CbD/EFb0 AB0CbD/EFb0 'ABC' AB0Cbb/bbb0 bb0bbA/BCb0 'ABCDEFGH' AB0CbD/EFb0 CD0EbF/GHb0 12345 1203b4/5bb0 b102b3/45b0 ZERO 0000b0/00b0 0000b0/00b0 ALL 'T' TT0TbT/TTb0 TT0TbT/TTb0 ALL '1234' 1203b4/12b0 3401b2/34b0 Příklad: Má-li položka C PIC XY-XY*(3)X(2)Y#XYt, pak příkaz MOVE 'PRAHA' TO C dosadí do položky C obsah P-R***AH#At. Poznámka: Přesun skupinové položky do alfanumerické editované položky se provádí alfanumericky bez edice (AN)! Příklad: 01 GR. 02 AN PIC X(6) VALUE '123456'. 01 AE PIC X/X/X/X/X/X/X. Příkaz "MOVE AN TO AE" dosadí do AE obsah 1/2/3/4/5/6/b, příkaz "MOVE GR TO AE" dosadí do AE obsah 123456bbbbbbb. Příklad: 77 AE PIC XXXBXXXBXXX VALUE '123 456 789'. 77 AF PIC XXXBXXXBXXX. Příkaz "MOVE AE TO AF" dosadí do AF obsah 123bb45b6b7. Numerický přesun (NU) Numerický přesun se provádí tehdy, když příjmová položka je numerická (což v COBOLu MX zahrnuje i numerickou editovanou položku!) a vysílající údaj je libovolný s výjimkou skupinové položky; jako vysílající údaje jsou však v numerickém přesunu zakázány alfanumerické literály neobsahující pouze cifry a figurativní konstanty jiné než ZERO, ZEROS, ZEROES. Pravidla: 1) Je-li vysílajícím údajem alfanumerická nebo alfanumerická editovaná položka, pracuje se s ní tak, jako kdyby místo ní stála rozpakovaná numerická položka o téže délce, s výpočtovou desetinnou tečkou za posledním místem a se znakem S ve vzoru. (Má-li tedy alfanumerická položka např. PIC X(6), přesun se provádí tak, jako kdyby šlo o numerickou položku s PIC S9(6) USAGE DISPLAY.) Je-li délka vysílající položky větší než 30 bytů, použije se pouze prvních 30 bytů vysílající položky. Vysílající položka by tedy měla obsahovat pouze cifry a případně též v levém půlbytu posledního bytu znaménko (3 nebo 4). 2) Je-li vysílajícím údajem alfanumerický literál obsahující pouze cifry, zpracuje se tak, jako kdyby byl uveden bez apostrofů; tedy např. místo '123456' se použije 123456. 3) Je-li vysílajícím údajem "ALL alfanumerický-literál" obsahující pouze cifry, vytvoří se nejprve cyklickým opakováním tohoto alfanumerického literálu ve směru zleva doprava fiktivní alfanumerický literál o takové délce, jaký je celkový počet dekadických řádů příjmové položky, a z něj se pak vytvoří nezáporný numerický literál tím, že se vnutí desetinná tečka na to místo, na němž se nachází ve vzoru příjmové položky. Tento numerický literál se pak použije jako skutečný vysílající údaj. Je-li příjmová položka exponenciální krátká nebo exponenciální dlouhá nemá smysl mluvit o počtu dekadických řádů, a proto se v tomto případě udělá přesun alfanumericky. Poznámka: Z důvodu kompatibility i srozumitelnosti programu se doporučuje nepřesunovat do numerické položky ani alfanumerickou resp. alfanumerickou editovanou položku ani alfanumerický literál resp. ALL-klauzuli, nýbrž přesunovat do ní pouze numerické položky, numerické literály a ZERO. 4) Hodnota získaná příjmovou položkou je určena pouze hodnotou vysílajícího údaje nezávisle na tom, zda vysílajícím údajem je položka nebo literál nebo ZERO nebo ALL-klauzule, případně jaké má klauzule PICTURE, USAGE apod. Hodnota vysílajícího údaje se upraví dle PICTURE příjmové položky; přebývající cifry se odříznou a na místa chybějících cifer se doplní bezvýznamné nuly. Při přesunu do exponenciální položky (krátké, dlouhé nebo znakové) se bere nejvýše tolik platných cifer hodnoty vysílajícího údaje, kolik je jich příjmová položka schopna pojmout (tj. dle typu počítače 16-18 platných cifer u exponenciální dlouhé a u exponenciální znakové položky a 7-9 platných cifer u exponenciální krátké položky; přesun numerické položky do exponenciální znakové položky se provádí přes pomocnou exponenciální dlouhou položku). Nakonec se takto získaná hodnota upraví dle USAGE příjmové položky, případně se převede do exponenciálního binárního resp. exponenciálního znakového tvaru atd. Je-li příjmová položka numerická editovaná, provedou se ediční úpravy předepsané pomocí klauzulí PICTURE, BLANK a SIGN u příjmové položky. 5) Může-li příjmová položka nabývat i záporných hodnot (u rozpakovaných, pakovaných a binárních položek je tomu tak při znaku S v PICTURE, u exponenciálních položek je tomu tak vždy, u numerických editovaných položek je tomu tak tehdy, obsahuje-li vzor nějaké vyjádření znaménka), bude její výsledné znaménko rovno znaménku vysílajícího údaje. Je-li příjmová položka rozpakovaná nebo pakovaná se znakem S v PICTURE, je při nezáporné hodnotě znaménkový půlbyte hexadecimálně 3, při záporné hodnotě je znaménkový půlbyte hexadecimálně 4. 6) Je-li příjmová položka rozpakovaná, pakovaná nebo binární bez znaku S v PICTURE, bude její výsledná hodnota vždy nezáporná; bude to absolutní hodnota z hodnoty vysílajícího údaje. U rozpakované nebo pakované příjmové položky bude znaménkový půlbyte vždy hexadecimální 3. (Ovšem jen za předpokladu, že vysílající údaj - je-li položkou - má numerický obsah odpovídající svému popisu.) 7) Při odřezávání přebývajících cifer za desetinnou tečkou (tj. vpravo) se neprovádí zaokrouhlování. Vždy se však zaokrouhluje při přesunu z exponenciální položky (krátké, dlouhé, znakové) do položky s pevnou řádovou tečkou a dále při přesunu jakékoliv položky do exponenciální znakové položky. Příklad: Příkaz "MOVE údaj TO A" způsobí následující obsazení položky A: hodnota | příjmová položka A vysílajícího|---------------------------------------------- údaje | PICTURE | USAGE | výsledný obsah A (hex.) ------------|----------|---------|------------------------- +3.25 | S99V999 | DISPLAY | 3033323530 +3.25 | S99V999 | COMP-3 | 032503 +3.25 | S99V999 | COMP | B20C0000 +3.25 | | COMP-1 | 00005040 +3.25 | | COMP-2 | 0000000000000A40 +3.25 |+99.99E+99| DISPLAY | +32.50E-01 (znakově) +3.25 | *,***.99-| DISPLAY | ****3.25b (znakově) -12.385 | S9V9 | DISPLAY | 3243 -3.45 | 999 | COMP-3 | 0033 12345.67 | S999PPP | COMP | 0C00 -126 | SV99 | DISPLAY | 3040 +0.005678 | VPPP99 | COMP-3 | 0673 '1234' | S9(7)V99 | COMP-3 | 0001234003 ALL '3' | S9(5)V9 | COMP-3 | 03333333 ALL '7' | 99V9 | COMP | 0903 ALL '9' | 9(8)V99 | DISPLAY | 39393939393939393939 ALL '468' | 9(4)V9(4)| DISPLAY | 3436383436383436 ALL '468' | 9(4)V9(4)| COMP-3 | 0468468463 Poznámka: Výpis hodnot v předchozím příkladě odpovídá způsobu uchovávání hodnot na počítačích pracujících s procesorem Intel 80286. To znamená, že například u binárních položek (USAGE COMP) obsahuje byte nejvíce vlevo řádově nejnižší bity a byte nejvíce vpravo řádově nejvýznamnější bity. Uvnitř jednotlivých bytů jsou jednotlivé bity obsazovány tak, že bit nejvíce vlevo má nejvyšší hodnotu a bit nejvíce vpravo nejnižší hodnotu. Např. číslo 1 je uloženo jako 0100, 10 jako 0A00, 255 jako FF00, 256 jako 0001 atd. U exponenciálních dlouhých položek (COMP-2) obsahuje byte nejvíce vpravo znaménko mantisy a část exponentu. Druhá část exponentu je na čtyřech bitech sousedního bytu. Mantisa je uchovávána normalizovaně ve dvojkovém tvaru, takže nejvýznamnější bit mantisy u nenulového čísla je vždy 1. Proto se hodnota tohoto bitu vůbec neuchovává a je "zamlčena". Exponent je dvojkový, takže hodnota položky je dána výrazem: mantisa * (2 ** exponent). Příklad: 01 GR. 02 AN PIC X(4) VALUE '1234'. 01 NU PIC 99V99. Přesun "MOVE GR TO NU" se provádí alfanumericky, takže do úseku paměti přiděleného položce NU se dosadí znakově 1234, čímž položka NU získá numerickou hodnotu 12.34. Naproti tomu přesun "MOVE AN TO NU" se provádí numericky (jakoby položka AN měla PIC S9999), takže numerická hodnota vysílajícího údaje je 1234 a položka NU získá numerickou hodnotu 34.00 a do jí přiděleného úseku paměti se dosadí obsah 3400. Poznámka: Je-li uvedeno několik příjmových položek, přesune se vysílající údaj postupně do všech. Příjmové položky mohou být různých typů, avšak každý z těchto částečných přesunů musí být přípustný. Je-li vysílajícím údajem položka, zjistí se nejprve její adresa a délka (tj. provede se případné indexování apod.), načež se do jednotlivých příjmových položek přesouvá vždy hodnota nacházející se na této adrese, aniž by se adresa vysílající položky vypočítávala pro každý přesun znovu. Příklad: 03 AN PIC X(5). 03 AE PIC X/X/X/X/X. 03 NU PIC 9(6)V99 COMP-3. Příkaz "MOVE 567 TO AN AE NU" dosadí do položky AN obsah 567bb (alfanumerický přesun), do položky AE obsah 5/6/7/b/b (alfanumerický přesun s edicí), a do položky NU obsah hexadecimálně 0000567003 (numerický přesun). Příklad: Nechť I = 2. Pak příkaz "MOVE 3 TO I, A(I)" dosadí I = 3, A(3) = 3. Naproti tomu příkaz "MOVE 3 TO A(I), I" dosadí A(2) = 3, I = 3. Pořadí příjmových položek není tedy obecně zaměnitelné. Příklad: Nechť I = 2, A(2) = 3, A(3) = 4. Při provádění příkazu "MOVE A(I) TO I, B" se nejdříve vypočítá adresa vysílajícího údaje A(2) a pak se hodnota 3 nalezená na této adrese dosadí postupně do I a do B, takže bude I = 3, B = 3. Náš příkaz není tedy ekvivalentní s dvojicí příkazů "MOVE A(I) TO I; MOVE A(I) TO B", po nichž by bylo I = 3, B = 4. Poznámka: Výsledek přesunu bude odpovídat pravidlům uvedeným v tomto odstavci 6.1. pouze za předpokladu, že vysílající a příjmová položka se v paměti nepřekrývají. Pokud by se vysílající a příjmová položka v paměti překrývaly, lze průběh a výsledek přesunu zjistit pouze prostudováním příkazů přeloženého programu. U alfanumerického přesunu může programátor využít překrývání, ví-li, že se přesun provádí byte po bytu (případně dvojice bytů do dvojici bytů) směrem zleva doprava. Např. při popisu 01 A. 02 B PIC X(30). 02 C PIC X(2970). příkaz "MOVE A TO C" způsobí, že položka A bude obsahovat stokrát opakovaný obsah položky B (viz též kapitola "Doporučení k optimalizaci programu"). Poznámka: Vysílajícím údajem smí být i podmínkové jméno. Při jeho zápisu lze uvést kvalifikaci, indexy jsou však nepovinné i v případě, že podmínková proměnná je popsána pod OCCURSem, a při uvedení by se ignorovaly. Příkaz MOVE pak pracuje přesně stejně, jakoby byl jakožto vysílající údaj uveden ten údaj, jenž je uveden v klauzuli VALUE resp. VALUES tohoto podmínkového jména jako první (může to být literál, figurativní konstanta, ALL-klauzule). Příklad: 03 A PIC 999 OCCURS 100. 88 B VALUE 15 THRU 23 12 5 THRU 8 56. ... MOVE B TO C. & ekvivalentní s "MOVE 15 TO C" Poznámka: Je-li vysílajícím údajem podmínkové jméno a příjmovou položkou jemu odpovídající podmínková proměnná, lze v příkazu MOVE vynechat část "TO příjmová-položka". Doplní se implicitně "TO podmínková-proměnná"; jsou-li však potřebné indexy, musí je uživatel uvést u podmínkového jména. Jsou tedy ekvivalentní příkazy "MOVE B(I)", "MOVE B TO A(I)" a "MOVE 15 TO A(I)". (Odpovídající "test podmínkového jména" se takto většinou stane pravdivým; výjimkou je, když údaj obsahuje nadbytečné nenulové cifry nebo byty nebo znaménko nebo když podmínková proměnná je editovaná nebo má klauzuli JUST atd.)