Míra abstrakce

Z minulých dílů už víte, že programovací jazyk není nic jiného, než určitým domluveným kódem psaný text, který se pak skrz kompilátor převádí do strojového kódu.

Jedno důležité členění programovacích jazyků, které je dle mého důležité pochopit, je míra abstrakce.

Nízká nebo žádná míra abstrakce

Programovací jazyk, který má nízkou nebo téměř žádnou míru abstrakce je vlastně jen převlečené zádávání instrukcí pro procesor ale v trochu přehlednější formě, než po jednotlivých bitech.

Níže následuje ukázka (zdroj: Wikipedie) pro srovnání.

  • Vlevo je strojový kód funkce pro výpočet Fibonacciho čísla v x86 instrukční sadě. Pro zkrácení místo 32-bitového zápisu instrukce 10001011010101000010010000001000 jsou jednotlivé instrukce uvedeny v hexadecimální formě.
  • Vpravo je zápis té samé funkce v „assembly“ v x86. Assembly se nepovažuje úplně za konkrétní programovací jazyk, je to spíš čitelnější forma zápisu svázaná s konkrétní instrukční sadou. Tzn. assembly pro x86 se bude lišit od assembly pro ARM64.

Strojový kód (x86, výpočet Fibonacciho čísla)

8B542408
83FA0077
06B80000
0000C383
FA027706
B8010000
00C353BB
01000000
B9010000
008D0419
83FA0376
078BD989
C14AEBF1
5BC3

Assembly (x86, výpočet Fibonacciho čísla)

_fibonacci:
        movl $1, %eax
        xorl %ebx, %ebx
.fibonacci_loop:
        cmpl $1, %edi
        jbe .fibonacci_done
        movl %eax, %ecx
        addl %ebx, %eax
        movl %ecx, %ebx
        subl $1, %edi
        jmp .fibonacci_loop
.fibonacci_done:
        ret

Psaní v assembly vyžaduje, že se vyznáte v instrukční sadě konkrétního čipu/procesoru, nad kterým programujete. To abyste se nezbláznili ze psaní strojového kódu napřímo.

Tak se místo toho zblázníte v assembly.

Na příkladu tohoto jednoduchého prográmku to zas tak složité není. x86 procesory obsahují různé „registry“ mezi kterými přesouváte bity (movl) a provádíte nad nimi bitové operace (xorl, addl, subl) a zároveň skáčete mezi instrukcemi (jbe, jmp, ret). Jak konkrétně se v x86 pracuje je mimo rozsah tohoto návodu.

Teoreticky je to možné napsat v assembly komplikovanější software, ve kterém zobrazujete nějaké grafické prvky, čekáte na vstup z klávesnice/myši a podobně, prakticky je ale téměř nereálné to rozchodit v rozumném čase.

Další nevýhodou psaní kódu s nízkou mírou abstrakce je fakt, že váš kód je svázán nejenom s konkrétní instrukční sadou ale i s konkrétní verzí instrukční sady a někdy i s konkrétním modelem procesoru.

Výhody a nevýhody nízkoúrovňového programování

Výhody:

  • máte možnost využít naplno fyzické možnosti konkrétního čipu nebo procesoru. Váš software může být plně optimalizovaný a extrémně rychlý.

Nevýhody:

  • je to šíleně složité a pracné, komplexnější software je prakticky nemožné napsat v rozumném čase.
  • váš software poběží jen na konkrétní instrukční sadě, na konkrétním typu procesoru ale i na konkrétním modelu čipu/procesoru. To nevadí, pokud programujete software pro řadu nějakých robotů se stejným čipem, ale o tomto typu programování tento návod není.

Vysoká míra abstrakce

„Vysokoúrovňové“ programovací jazyky umožňují psát v kodu, který je blíže k přirozené řeči a zbavují nás závislosti na konkrétní instrukční sadě. Už nás nezajímají konkrétní instrukce pro procesor, protože kód, který napíšeme, přeloží do strojového kódu kompilátor.

Níže je ukázka funkce pro výpočet Fibonacciho čísla v programovacím jazyce C.

int fibonacci(int n)
{
    if (n <= 1)
        return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

Všimněte si, že ten program je podstatně kratší! Zabírá pouze 6 řádků textu zatímco v Assembly ten samý kód zabírá 14 řádků textu. Navíc v něm vidíte anglická slova jako „if“ nebo „return„. Zároveň se zde vyskytuje „int“ a z minulých kapitol byste už měli vědět, že „int“ reprezentuje celé 32 bitové číslo. (pozn.: v tuto chvíli není třeba kódu rozumět)

Tento kód se ale musí do strojového kódu zkompilovat pomocí kompilátoru. Přestože kompilátory jsou jedny z nejsložitějších programů, které na světě existují, tak nikdy nedokážou žádnou aplikaci zkompilovat opravdu optimálně (snad jen kromě velmi jednoduchých, ukázkových programů, jako ten výše).

V důsledku toho lze říct, že jakýkoliv software, který se postaví skrz zkompilovaný programovací jazyk, téměř nikdy nevyužívá 100% možnosti výkonu procesoru pro úlohu, kterou chce vykonat.

Ono to ve skutečnosti nevadí. Procesory jsou brutálně rychlé a moderní kompilátory jsou velmi dobře udělané. Zkušeného „běžného“ ajťáka vůbec nezajímá, jak vypadá strojový kód vygenerovaný kompilátorem. Celá pointa programovacího jazyka je, že chceme vyrábět software v kódu, který je mnohem přehlednější, srozumitelnější a intuitivnější, než psaní v assembly/strojovém kódu. V kódu, se kterým je jednodušší psát mnohem komplexnější software.

Výhody a nevýhody vysokoúrovňového programování

Výhody

  • V programovacím jazyce je možné napsat mnohem komplexnější software
  • Kompilátory podporují celou řadu instrukčních sad. Náš software je možné provozovat na více zařízeních.

Výhody

  • V programovacím jazyce je možné napsat mnohem komplexnější software
  • Kompilátory podporují celou řadu instrukčních sad. Náš software je možné provozovat na více zařízeních.

Shrnutí

  • Programovací jazyky se podle míry abstrakce dělí na nízkoúrovňové a vysokoúrovňové
  • Nízkoúrovňové jazyky jsou jen o něco čitelnější způsob, jak zapisovat instrukce přímo ve strojovém kódu.
  • Vysokoúrovňové jazyky jsou na strojovém kódu nezávislé. Jsou konstruovány hlavně tak, aby byly přehledné, intuitivní a aby se v nich dal psát komplexnější software.