/ janturon.cz / Od kodéra k analytikovi / Skoky

Skoky

Na počátku byl skok. Bylo to ještě v dobách assembleru, kdy nerdi uměli přímo hexaeditovat spustitelný kód strojových instrukcí a počítače běhaly v reálném módu: program se načetl na adresu 100h a celý stroj včetně operačního systému patřil jen jeho instrukcím, které volaly přímo služby BIOSu, případně operačního systému. Celý příběh podbarvovala problematika práce s pamětí, kde stačil jediný neuvážený skok, a jediné funkční tlačítko na počítači bylo reset. (Někdy se k tomu divoce rozblikal monitor nebo zapískal PC-speaker.) Díky tomuto nebezpečí se nad mnemonikami assembleru vytvořily následující konstrukce:

LOOP

Skok zpět, pokud je CX=0, tedy opakování s předem známým počtem kroků, vedlo ke konstrukcím while a for (která byla rozšířena o iniciační a iterační příkaz).

CMP - JZ (JNZ)

Podmíněný skok, je-li výsledek rozdílu nulový (nebo ne), je dnes znám jako konstrukce if (-else).

CALL - RET

Nepodmíněný skok s návratem. Jazykově se to promítlo do vytvoření procedur, později funkcí (procedury obohacené o návratovou hodnotu), později metod (funkce zabalené do tříd).

JMP

Nepodmíněný skok. Program všeho nechá a následující instrukce pokračuje na úplně jiném místě v paměti (třeba zprostřed cyklu doprostřed funkce). Přestože některé jazyky (PHP, Basic) toto umožňují příkazem GOTO, dnes je použití nepodmíněného skoku považováno za antivzor, protože je to v podstatě hack. Radikálně se snižuje přehlednost kódu (viz špagetové programování) a chyby se velmi těžko dohledávají, protože je narušena kontinuita (instrukčního) časoprostoru.

Nepodmíněné skoky jsou používány v mechanismu vyjímek. Vyjímka uloží aktuální stav zásobníku a zničí všechny automatické objekty v aktuálním bloku. Není-li odchycena mechanismem try-catch, ze zásobníku se odebere další úroveň zanoření, zničí se automatické objekty aktuálního bloku, a tak dále až do dna zásobníku nebo do zpracování vyjímky. Celý mechanismus je časově náročný, prodleva při zpracování vyjímky bývá postřehnutelná a není-li ošetřena, spotřebuje se značné množství procesorového času, než je aplikace ukončena.

Příkaz break skočí za aktuálně prováděný cyklus. Přestože po skončení cyklus tak nemusí proběhnout předepsaný počet kroků (a hodnota indexu po skončení nemusí být rovna poslední očekávané hodnotě), kód je čitelný (díky tomu, že těla dobře navržených cyklů bývají krátká až triviální).

Tímto neduhem netrpí příkaz continue, který skočí na začátek prováděného cyklu (a vynechá tak příkazy za ním).