<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Karel</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Od Karla k mikroprocesorům</title>
  <!--date>2011-09-xx</date-->
  <date>2026-09-11</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
  <style>
      img.side-by-side { display: inline; vertical-align: middle; }
  </style>
</meta>
<!--
  „“–
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Úvod">

    <p>
        V této přednášce budeme s Karlem chvíli počítat. Nemůžeme – alespoň ne tak jednoduše – moc daleko, jenom do osmi, ale kupodivu nám to bude bohatě stačit, abychom si ukázali, jak se chová procesor počítače. A že na rozdíl od abstraktní matematiky nemáme k dispozici nekonečně mnoho místa.
    </p>

</slide>
<slide title="Sčítání I">

    <p>
        Začneme tím nejjednodušším – sčítáním. Představme si, že Karel stojí na nějakém políčku a že na políčcích hned vlevo a vpravo vedle něj je nějaký počet značek, pro začátek se součtem nejvýše osm. Máme za úkol na políčko, na kterém Karel stojí, položit tolik značek, kolik činí součet značek vlevo a vpravo. Neboli ze situace..
    </p>
    <img class="center" src="_files/math/add_1.jpg" width="152" height="153" alt="sčítání – počáteční stav" />
    <p>
        ..se dostat k výsledku:
    </p>
    <p class="center">
        <img class="side-by-side" src="_files/math/add_2a.jpg" width="155" height="156" alt="sčítání – koncový stav (nedestruktivní)" />
        anebo
        <img class="side-by-side" src="_files/math/add_2b.jpg" width="156" height="156" alt="sčítání – koncový stav (destruktivní)" />
    </p>

</slide>
<slide title="Sčítání II">

    <p>
        Z důvodů, které si vysvětlíme až později, budeme všem třem políčkům, se kterými budeme pracovat, říkat <strong>registry</strong>. S tímto termínem by se úloha dala přeformulovat např. takto:
    </p>
    <blockquote>
        Napište program, který sečte hodnoty v registrech VLEVO a VPRAVO a výsledek uloží do registru STŘED.
    </blockquote>
    <p>
        Když se nad tím trošku zamyslíte, stačí vlastně zkopírovat obsah obou políček po stranách do prostředního políčka, což je jednoduchý rekurzivní algoritmus (náš Karel jinak čísla než právě rekurzí počítat neumí). A jde to zjevně zařídit dvěma způsoby – buď hodnoty opravdu pouze zkopírujeme, takže v postranních políčkách původní značky zůstanou, nebo je destruktivně přesuneme doprostřed, takže z postranních políček zmizí. Ukážeme si oba způsoby.
    </p>

</slide>
<slide title="Sčítání s vynulováním registrů">

    <p>
        Program <code>SEČTI</code> popisuje, jak se mají levé a pravé políčko sečíst, program <code>PŘENOS</code> se pak stará o vlastní rekurzivní přenosení libovolného počtu značek z těchto políček do středu:
    </p>
    <example lang="karel">
        ČELEM VZAD
          RYCHLE
            VLEVO VBOK
            VLEVO VBOK
          POMALU
        KONEC

        PŘENOS
          KDYŽ JE ZNAČKA
            ZVEDNI
            PŘENOS
            POLOŽ
          KONEC, JINAK
            ČELEM VZAD
            KROK
            ČELEM VZAD
          KONEC
        KONEC

        SEČTI
          VLEVO VBOK
          KROK
          PŘENOS
          ČELEM VZAD
          KROK
          PŘENOS
          VLEVO VBOK
        KONEC
    </example>

</slide>
<slide title="Sčítání se zachováním obsahu registrů">

    <p>
        Program, který zachová registry (tedy levé a pravé políčko) nedotčeny, je prakticky úplně stejný, pouze je třeba v rekurzivním kroku kopírování ponechat originální značky na postranních políčkách. Jelikož je to užitečné cvičení, řešení zde neuvádím, pouze nápovědu:
    </p>
    <p>
        Jediný způsob, jakým náš Karel umí spočítat, kolik je na políčku značek, je, že je nejdříve rekurzivně všechny sebere. Jakmile se z rekurze začne vracet, příslušná část kódu se provede právě tolikrát, kolik bylo na políčku značek, ale Karel jinak sám neví, jaké toto číslo je. V <a href="?slajd=4">předchozím řešení</a> jsme v této části kódu značky pokládali pouze na středové políčko, v tomto řešení je zjevně potřebujeme kromě středového políčka položit i na políčko, ze kterého jsme je vybrali. Také stejným počtem krát.
    </p>

</slide>
<slide title="Souvislost s procesory I">

    <p>
        Světe div se, ale v podstatě přesně tak, jak jsme si naprogramovali sčítání značek, fungují i skutečné procesory (dnes už nejen) v počítačích:
    </p>
    <ol>
        <li>
            Data, se kterými program pracuje, jsou uložena v paměti počítače.
        </li>
        <li>
            Dvě čísla, která chceme sečíst, nakopírujeme z příslušných paměťových adres na odpovídající registry procesoru.
        </li>
        <li>
            Procesor provede s čísly ve vstupních registrech požadovanou operaci a její výsledek uloží do vhodného výstupního registru.
        </li>
        <li>
            Z výstupního registru je číslo zkopírováno na požadované místo v paměti počítače.
        </li>
        <li>
            Program pokračuje zkopírováním dalších dvou čísel do vstupních registrů.
        </li>
        <li>
            ...
        </li>
    </ol>

</slide>
<slide title="Souvislost s procesory II">

    <p>
        A co když bude značek k sečtení více než osm? Správná otázka. A v případě našeho programu si můžete snadno vyzkoušet, že program zhavaruje a Karel vypíše hlášku o tom, že na dané políčko nemůže uložit víc než osm značek.
    </p>
    <p>
        Skutečný procesor má nepřekvapivě také velikost registrů konečnou, ale většinou nebývá tak malá jako u našeho Karla. Řekněme pro jednoduchost, že má třebas kapacitu jednoho bajtu, čili lze do ní zapsat nejvyšší číslo 255. Co se stane, pokud bude výsledek součtu větši? Typicky asi toto:
    </p>
    <blockquote>
        Jelikož do výstupního registru se prostě víc dat než 8 bitů (tj. jeden bajt) nevejde, procesor zapíše pouze (nižší) část výsledku o délce osmi bitů a do jiného – tzv. <strong>příznakového</strong> – registru dá vědět (typicky nastavením některého z jeho paměťových bitů), že došlo k tzv. <strong>přetečení</strong>, tj. že daná operace vrátila výsledek větší, než je možné zaznamenat.
    </blockquote>
    <p>
        Je zjevné, že v naší osmibitové aritmetice se správný výsledek dozvíte snadno – jestliže je nastavený příznakový registr, k zaznamenané hodnotě stačí přičíst 255. Samozřejmě výsledek pak musíte uložit do paměti na dvě jednobajtové adresy, do jedné se přece nevejde.
    </p>

</slide>
<slide title="Odčítání">

    <p>
        Odečítání dvou čísel se dá naprogramovat (pomocí rekurze) opět velmi snadno a ponechávám ho za domácí úkol ^_~ Opět můžete vstupní registry buď zachovat, nebo vymazat. A opět vás čeká nepříjemné překvapení – to když se pokusíte od menšího čísla odečíst větší.
    </p>
    <p>
        Karel v takovémto případě opět zhavaruje a zahlásí, že na políčku již není žádná značka, kterou by mohl odebrat. Ale skutečný procesor se s tím samozřejmě opět nějak popasuje. Přitom:
    </p>
    <ul>
        <li>
            Procesor umí (nějakým způsobem) zaznamenat záporná čísla a výsledek patřičným způsobem uloží.
        </li>
        <li>
            Procesor se zápornými čísly pracovat neumí, nebo popravdě spíš po něm zrovna chceme, aby s nimi právě teď nepracoval, takže výsledek prozměnu tzv. <strong>podteče</strong> (pod nulu) a zase dostaneme na první pohled nesmyslný výsledek.
        </li>
    </ul>

</slide>
<slide title="Komentář">

    <p>
        To zdaleka nejzajímavější na tom všem je, že různé procesory umí pracovat s různě velkými čísly různě rychle/pomalu a ještě navíc různě přesně (zdaleka ne každé číslo totiž vůbec můžete v počítači nějak uložit!). Takže v reálných programech dává smysl omezit se na konkrétní podmnožinu čísel a řešit problém jenom v ní. (A postarat se o případy, kdy kvůli tomu narazíte do zdi :-)
    </p>
    <p>
        Teď byste se ještě mohli zeptat, k čemu to vlastně je dobré, že procesor dokáže sečíst/odečíst (a modernější procesory mnohem víc) dvě čísla z paměti počítače. Kromě čistě matematických výpočtů, kde to nikoho nepřekvapí<sup>*</sup>, pro vysvětlení snad bude stačit tento příklad: <em>Co je vidět na monitoru, to je obrazem nějakého úseku paměti (moderními grafickými kartami si to nebudeme komplikovat). Takže změnit v tomto úseku nějaká čísla nějakým výpočtem znamená změnit to, co je na monitoru zobrazeno.</em>
    </p>
    <note>
        <sup>*</sup> Jiné přednášky se budou podrobně věnovat tomu, jak se čísla v počítači ukládají a jak se s nimi pracuje. Protože nemáme k dispozici nekonečně mnoho paměti (a navíc by se s čísly v takovém případě počítalo fakt špatně a pomalu :), výpočty jak v celých číslech, tak především v reálných podléhají mnohým a pro neznalé nečekaným omezením. Nazdory běžnému přesvědčení, že počítač je od slova „počítat“, tak mu to počítání přece musí jít, to není s výpočty v počítačích vůbec tak jednoduché.
    </note>

</slide>


</lecture>
