Zoznam úloh

3. Assembler

Zadanie

Novinka: popis nemusíš odovzdávať len na konci kola, ale môžeš už priebežne. My sa ti ho pokúsime čo najskôr opraviť a ak nebudeš mať všetko alebo niečo nebude správne, tak tvoj popis môžeš doplniť/opraviť a znovu ho odovzdať.

Červená Čiapočka ďalej kráčala lesom, keď zrazu vedľa seba uvidela kopu smetí. Bolo tam všeličo – pokazené jedlo, plastové sáčky, staré noviny… a dokonca aj nejaký veľmi starý počítač. To Čiapočku veľmi zaujalo, a tak sa naňho pozrela bližšie. Dokonca išiel aj zapnúť! Ale nemal žiadne okná ani myš, dali sa tam len písať nejaké príkazy. Ako sa taký počítač vôbec používa? Vedľa neho bol medzi smeťami aj papier s návodom, a tak sa Červená Čiapočka rozhodla, že ho vyskúša.

Úloha

Táto úloha je interaktívna. Na tejto stránke nájdeš simuláciu starého počítača, návod, ako ho programovať, a zadania úloh, ktoré máš vyriešiť. Stránka vie automaticky overiť, či tvoj program správne rieši nejakú úlohu. Ako popis odovzdaj tvoje programy, ktoré odovzdáš na stránke s počítačom, nemusíš k nim písať nič viac.

1

Chceme najprv spraviť niečo ako “ak je v pamäti na adrese 0 číslo 1, tak urob niečo.” Ale také nevieme urobiť priamo, lebo vieme iba porovnávať čísla v pamäti a podľa toho skočiť na nejaké miesto v programe.

Budeme chcieť zisťovať, či je niečo 1 alebo 2, takže si tieto čísla najprv uložíme do pamäte. Potom sa urobíme v programe miesta (labely), kam dáme to, čo chceme spraviť. Potom, čo sa spustí časť programu, ktorá zodpovedá nejakej podmienke (napr. že tam je 1), musíme ešte skočiť na koniec programu, aby sme hneď potom nepustili tú časť, ktorá už patrí k ďalšej podmienke.

set 1 1
set 2 2

eq 0 1 je-to-1
eq 0 2 je-to-2
set 10 10
jump koniec

label je-to-1
set 10 5
jump koniec

label je-to-2
set 10 7

label koniec

2

Obvod obdĺžnika so stranami $a \times b$ je $2 \cdot (a + b)$, takže stačí sčítať tie dve čísla a potom výsledok vynásobiť dvomi. Vynásobiť dvomi je to isté ako sčítať so sebou.

add 0 1 10
add 10 10 10

3

Násobenie je vlastne iba opakované sčítavanie. Môžeme si to predstaviť tak, že máme dva vstupy $a$ a $b$ (tie čísla, čo chceme vynásobiť) a jeden výstup, čo je na začiatku 0 (a na konci tam chceme mať výsledok).

V jednom kroku pripočítame $a$ k výstupu a toto celé zopakujeme $b$-krát. Ako ale spravíme opakovanie?

Máme v pamäti číslo $b$, ktoré nepotrebujeme na nič iné, iba nám hovorí, že máme niečo zopakovať toľkokrát. Môžeme od neho teda v každom kroku odpočítať $1$ a keď sa dostaneme na nulu, tak sme tých krokov spravili presne $b$.

Opakovanie potom spravíme tak, že dáme label na začiatok opakovania a keď prídeme na koniec, tak skočíme naspäť na začiatok. Ak je ale $b = 0$, tak skočíme von z opakovania na koniec programu.

set 2 1  # budeme chciet odpocitavat 1

label zaciatok
eq 1 3 koniec  # ak je B = 0 (na adrese 3 je od zaciatku 0) tak skoncime
add 10 0 10    # pripocitame A k vysledku
sub 1 2 1      # odpocitame 1 od B
jump zaciatok  # a opakujeme

label koniec

4

Spravíme niečo podobné ako pri násobení. Dajme tomu, že chceme vydeliť čísla $a$ a $b$. Deliť budeme tak, že budeme od $a$ postupne odpočítavať $b$ a počítať, koľkokrát sme to spravili.

Budeme mať teda výsledok, čo bude na začiatku $0$ a v každom kroku pripočítame $1$, a zvyšok, čo bude na začiatku $a$ a v každom kroku odpočítame $b$. Takto zrátame, “koľkokrát sa $b$ zmestí do $a$”, čo je presne $a/b$, a časť, ktorá sa nezmestí celá, je presne zvyšok.

Toto opakujeme, kým je $a$ aspoň $b$. Ak je $a$ menej ako $b$, tak už nám ostáva len zvyšok.

set 2 1    # budeme chciet odpocitavat 1
copy 0 11  # nastavime zvysok na A

label zaciatok
lt 11 1 koniec  # ak je aktualny zvysok < B, tak koncime
sub 11 1 11     # od aktualneho zvysku odpocitame B
add 10 2 10     # k podielu pripocitame 1
jump zaciatok

label koniec

5

Aby sme vedeli zrátať ďalší člen Fibonacciho postupnosti, potrebujeme vedieť tie posledné dva pred ním. Budeme si teda pamätať aktuálne dva členy a v ďalšom kroku vypočítame ten ďalší. Opakovanie spravíme rovnako ako v minulých úlohách.

set 1 1    # budeme chciet odpocitavat 1
set 10 0   # prvy clen
set 11 1   # druhy clen

label zaciatok
eq 0 2 koniec  # ak uz nam ostava 0 opakovani, tak skoncime
add 10 11 12   # na adresu 12 si spocitame dalsi clen
copy 11 10
copy 12 11     # nastavime aktualne dva cleny na tie dalsie dva
sub 0 1 0      # uz nam zostava o jedno opakovanie menej
jump zaciatok

label koniec
Pre odovzdávanie sa musíš prihlásiť.