SimHYMN mikroprocesszor szimulátor
Fejezetek
- Egyszerűbb programok
- Soros (szekvenciális) programok
- Elágazás
- Ciklusok
- Programozási tételek
-
- Gyakorlat (PDF)
- Zárthelyi (PDF)
A SimHYMN egy Java nyelven írt program, amely "szimulál":
- egy egyszerű
- 8 utasításos
- 30 byte memóriájú (program és adat közös tárhelyen)
mikroprocesszort (CPU - Central Processing Unit).
Segítségével könnyen érthetővé válik, hogyan hajtja végre a CPU a programot.
A CPU szimulátor jellemzői:
- PC (program counter/program számláló) - speciális célú regiszter
- IR (instruction register/utasítás nyilvántartás) - speciális célú regiszter
- AC (accumulator/akkumulátor) - általános célú regiszter
- memóriába ágyazott I/O egység (30-as címen az input, 31-es címen az output)
Letöltése, gyakorlat, zh:
- innen (ez működik is!)
- cburch.com
- Számítógépek belső felépítése - gyakorlat (PDF)
- Informatikai rendszerek alapjai - zh minta (PDF)
Futtatás (a programot tartalmazó könyvtárban ill. bárhonnan):
- java -jar hymn.jar (Linux alatt - parancssorból)
- java -jar hymn.jar (Windows alatt - ugyanígy CMD parancssorból)
vagy - java -jar elérési_út/hymn.jar (Linux alatt - parancssorból)
- java -jar elérési_út\hymn.jar (Windows alatt - parancssorból)
Utasítások
Minden utasítás egy byte-os (8 bites), amelyben az első 3 bit az utasításkód (azaz mit kell tenni), az utolsó 5 bit pedig az operandus címe (azaz melyik memóriarekesz tartalmával).
Csak 30 memóriarekesz címezhető (00000-11101), mert az utolsó két memóriarekesz (11110 és 11111) extra jelentésű:
- 11110 (decimális 30) - billentyűzetről vár adatbevitelt az AC-ba (input)
- 11110 (decimális 30) - képernyőre visz ki adatot az AC-ból (output)
Tehát ezek szerepe memóriába ágyazott input ill. output (I/O).
Egy kicsit precízebben:
- 10011110 - LOAD 11110 rövidíthető READ-nek (input)
- 10111111 - STORE 11111 rövidíthető WRITE-nak (output)
(Adatbevitel után nyomjunk "Enter" billentyűt!)
Kód | Mnemonik | Leírás |
---|---|---|
000 | HALT | nem történik semmi |
001 | JUMP | PC := operandus (ugrás az operandus/op. címre) |
010 | JZER | ha AC = 0, akkor PC := operandus, egyébként pedig PC := PC + 1 (következő címre) |
011 | JPOS | ha AC > 0, akkor PC := operandus, egyébként pedig PC := PC + 1 (következő címre) |
100 | LOAD | AC := M[data]; PC := PC + 1 (az op. által megcímzett memóriatartalom betöltése AC-be) |
101 | STORE | M[data]:=AC; PC := PC + 1 (AC tartalmának kiírása az op. által megcímzett memóriába) |
110 | ADD | AC := AC + M[data]; PC := PC + 1 (AC-hez hozzáadja az op.sal megcímzett memória tartalmát) |
111 | SUB | AC := AC - M[data]; PC := PC + 1 (AC-ből kivonja az op.sal megcímzett memória tartalmát) |
Egyszerűbb programok
Programozás lehetséges módszerei
- biteket kattintgatva (2. sárga oszlop)
- utasítás beírásával (3. oszlop)
- Memory/Open Image ... (image/memóriakép fájlból)
- Assembler/Show Editor
- Assembler/Assemble From File ... (assembly fájlból)
Jelölések az alábbi programokban
- bináris - 10110100 (nincs külön előtag)
- hexadec. - xB4
- decimális - d180 (= 128+32+16+4 = 11*16+4)
1. program
Előkészítés: program - 00000-tól adat - 10100-ba (legyen például 1100, xC, d12) Feladat: Töltsük a fenti cím tartalmát az akkumulátorba! Írjuk ki az akkumulátor tartalmát! Állj! Gépi kódban Assembler nyelven binárisan hexa dec. 100 10100 94 148 LOAD 10100 101 11111 BF 191 STOR 11111 000 00000 00 0 HALT
2. program (örökös ciklus)
Előkészítés: program - 00000-tól adat - 10100-ba (legyen például 0001, x01, d1) Feladat: Mit csinál a program? Hogy lehetne 8-asával növelni az AC-t? Gépi kódban Assembler nyelven binárisan hexa dec. 110 10100 xD4 -44 ADD 20 001 00000 x20 32 JUMP 0
Soros (szekvenciális) programok
Összeadások
# Két bekért szám összeadása, eredmény kiírása READ # 1. operandus bekérése az AC-ba (LOAD 30 ugyanez) STOR R1 # 1. operandus mentése R1 címre (változóba) READ # 2. operandus bekérése AC regiszterbe ADD R1 # AC = AC + R1 operandusok össszeadása WRITE # AC kiírása az outputra (STORE 31 is ugyanez) HALT # vége, nem megyünk tovább ... R1: 0 # helyfoglalás az R1 változónak, kezdőértéke 0
# Két memóriaregiszter összeadása, eredmény kiírása # Ellenőrizzük az eredményt (kettes komplemens!) LOAD R1 ADD R2 WRITE HALT # Ne felejtjük el futtatás előtt feltölteni R1: 13 R2: -45
# Három memóriaregiszter összeadása, eredmény kiírása # Mi a feltétele, hogy helyesen működjön? ADD R1 ADD R2 ADD R3 WRITE HALT R1: 13 R2: -45 R3: 72
Regiszterek cseréje
# Cseréljük fel az R1 és R2 regiszterek tartalmát # Van-e hiba a programban? (Mindenféle bemenő adatnál?!) # Hogyan javítható? READ STORE R1 READ STORE R2 LOAD R1 # R1->R0, R2->R1, R0->R2 STORE R0 # használjuk a segédregisztert LOAD R2 STORE R1 LOAD R0 STORE R2 # R0 a segédregiszter R0: 0 R1: 0 R2: 0
Elágazás
Előjel (+,0,-) eldöntése
# Szám előjelének (+,0,-) eldöntése # ha pozitív, 1-et, ha zérus, 0-t, ha negatív, -1-et ír ki, és leáll READ # szám beolvasása JZER zerus # ha 0, ugrás oda JPOS pozitiv # ha pozitiv, ugrás oda #negativ # ha negatív, idecsorog LOAD Km WRITE # kiírom a -1-et HALT pozitiv: LOAD Kp WRITE # kiírom az 1-et HALT zerus: LOAD K0 WRITE # kiírom a 0-t HALT Kp: 1 # 1 konstans - pozitív szám jelzésére K0: 0 # 0 konstans - zérus jelzésére Km: -1 # -1 konstans - negatív szám jelzésére
Melyik nagyobb?
# Melyik nagyobb a két bemenő szám közül? # Ha az első a nagyobb, 1-et, ha a második, 2-t, ha egyenlők, 0-t írjunk ki! READ STORE R1 READ STORE R2 LOAD R1 SUB R2 JPOS elso LOAD R2 SUB R1 JPOS masodik # egyenlők LOAD R0 WRITE HALT elso: LOAD R1 WRITE HALT masodik: LOAD R2 WRITE HALT # konstansok a kiíráshoz R0: 0 R1: 1 R2: 2
Ciklusok
Számsor összeadása
Az eredeti Gauss probléma: 1 + 2 + 3 + ... + 100 = ? (Állítólag kisiskolás korában adta fel az osztálynak a tanító bácsi, hogy hosszú időre lekösse a nebulókat, de a kis Gauss gyorsan megoldotta a következőképpen: 1+100=101, 2+99 is 101, egészen 50+51=101-ig, azaz 50 pár 101 egyenlő 50x101=5050.)
# Gauss feladata egyszerűsítve (5+4+...+1=?) # Megoldás elöltesztelő ciklussal START: LOAD i JZER END ADD SUM STOR SUM LOAD i SUB EGY STOR i JUMP START END: LOAD SUM WRITE HALT # változók kezdőértének beállítása SUM: 0 # összeg helye EGY: 1 # visszaszámláláshoz i: 5 # ciklusváltozó
# Gauss feladata egyszerűsítve (5+4+...+1=?) # Megoldás hátultesztelő ciklussal START: LOAD SUM ADD i STOR SUM LOAD i SUB EGY STOR i JPOS START LOAD SUM WRITE HALT # változók kezdőértének beállítása SUM: 0 # összeg helye EGY: 1 # visszaszámláláshoz i: 5 # ciklusváltozó
# változók kezdőértének beállítása SUM: 0 # összeg helye EGY: 1 # visszaszámláláshoz i: 5 # ciklusváltozó # Gauss feladata egyszerűsítve (5+4+...+1=?) # Megoldás hátultesztelő ciklussal START: LOAD SUM ADD i STOR SUM LOAD i SUB EGY STOR i JPOS START LOAD SUM WRITE HALT
Szorzás
# Szorzás hátultesztelő ciklussal # a x b = b + ... + b + b # a. 2. 1. START: LOAD b ADD ab STOR ab LOAD i SUB EGY STOR i JPOS START LOAD ab WRITE HALT # változók kezdőértének beállítása ab: 0 # szorzat helye a: 3 # szorzó b: 4 # szorzó i: 3 # ciklusváltozó EGY: 1 # visszaszámláláshoz
# Szorzás hátultesztelő ciklussal - előző javítása # a x b = b + ... + b + b # a. 2. 1. LOAD a STOR i START: LOAD b ADD ab STOR ab LOAD i SUB EGY STOR i JPOS START LOAD ab WRITE HALT # változók kezdőértének beállítása ab: 0 # szorzat helye a: 7 # szorzó b: 5 # szorzó i: a # ciklusváltozó EGY: 1 # visszaszámláláshoz
# Szorzás hátultesztelő ciklussal - bekért szorzók # a x b = b + ... + b + b # a. 2. 1. # Reset után (újra futtatva) hibás eredményt ad! Miért? Javítsuk ki! READ STOR a STOR i READ STOR b START: LOAD b ADD ab STOR ab LOAD i SUB EGY STOR i JPOS START LOAD ab WRITE HALT # változók kezdőértének beállítása ab: 0 # szorzat helye a: 0 # szorzó b: 0 # szorzó i: 0 # ciklusváltozó (kezdőérték: a) EGY: 1 # visszaszámláláshoz
Hatványozás
# Kettő hatványainak kiírása 64-ig # Szerző: Marton Balázs (GMGEPV) # 2011.09.28. LOAD egy # 1 -> AC STOR sum # 1 -> sum (2 nulladik hatványa) begin: # ciklus kezdete WRITE # kiírom az aktuális AC-t ADD sum # AC = 2AC STOR sum # AC -> sum JPOS begin # ugrunk, ha még pozitiv az összeg, különben túlcsordul egy: 1 # 1 konstans sum : 0 # 2 hatványok ebben
Paritás (páros/páratlan) eldöntése
# Paritás (páros/páratlan) eldöntése # ha páros, 0-t, ha páratlan, 1-et ír ki, és leáll # Működik-e a 0 számra? Ha nem, hogyan javítható? READ # szám (pozitív legyen) beolvasása ciklus: SUB K2 # csökentgetjük 2-vel JPOS ciklus # ugrunk, amíg pozitív JZER paros # ha 0-ra csökkent, páros volt, egyébként páratlan #páratlan LOAD K1 WRITE # kiírom az 1-et HALT paros: LOAD K0 WRITE # kiírom a 0-t HALT K0: 0 # 0 konstans - ez jelzi kiíráskor, hogy páros K1: 1 # 1 konstans - ez jelzi kiíráskor, hogy páratlan K2: 2 # 2 konstans
Maradékos osztás
# Feladat: Kérjünk be két számot, számítsuk ki és írjuk ki (egész osztással) # a hányadost és a maradékot! # Kérdés: Újra futtatva mire kell ügyelni? # Miért töröltem a végéről az "m: 0" változót? Tegyük vissza (a maradéknak)! READ # Be: a STOR a READ # Be: b STOR b ciklus: LOAD h ADD egy # h := h + 1 STOR h LOAD a SUB b # a := a -b STOR a JPOS ciklus JZER egyenlok # a = 0 már LOAD h SUB egy WRITE # Ki: hányados LOAD a ADD b WRITE # Ki: maradék HALT egyenlok: LOAD h WRITE LOAD zero WRITE HALT # Konstans és változók tárhelye zero: 0 egy: 1 a: 0 # elsőként bekért számnak (osztandó) b: 0 # másodikként bekért számnak (osztó) h: 0 # hányadosnak
Programozási tételek
Összegzés tétele
# Tömb elemeinek öszeadása # Mivel nincs indexregiszter, ezért az utasítást módosítjuk! ciklus: LOAD TOMB # tömbelem betöltése (ezt az utasítást módosítja a program futás közben) STORE FIX # tartalmát fix helyre tesszük ADD SUM # összegzés STORE SUM LOAD ciklus # betöltjük a ciklus címen lévő utasítást (most adatként kezeljük) ADD EGY # a cím az alsó biteken van, növeljük, így a következő tömbelemre mutat majd !!!!! STORE ciklus # visszamentjük a módosított utasítást LOAD DRB SUB EGY # ciklusváltozó csökkentése STORE DRB JPOS ciklus # visszaugrunk LOAD SUM # összeg betöltése WRITE # kiírása HALT # itt a vége, fuss el véle # tömbelemszám és tömb, egyéb konstansok és változók DRB: 6 TOMB: 13 -3 7 -40 27 3 SUM: 0 EGY: 1 FIX: 0
Maximumkiválasztás tétele
# Tömb elemeinek öszeadása # Mivel nincs indexregiszter, ezért az utasítást módosítjuk! ciklus: LOAD TOMB # tömbelem betöltése (ezt az utasítást módosítja a program futás közben) STORE FIX # tartalmát fix helyre tesszük LOAD MAX SUB FIX JPOS atugrik LOAD FIX STORE MAX atugrik: LOAD ciklus # betöltjük a ciklus címen lévő utasítást (most adatként kezeljük) ADD EGY # a cím az alsó biteken van, növeljük, így a következő tömbelemre mutat majd !!!!! STORE ciklus # visszamentjük a módosított utasítást LOAD DRB SUB EGY # ciklusváltozó csökkentése STORE DRB JPOS ciklus # visszaugrunk LOAD MAX # maximum betöltése WRITE # kiírása HALT # itt a vége, fuss el véle # tömbelemszám és tömb, egyéb konstansok és változók DRB: 6 TOMB: 72 -3 7 14 27 53 MAX: -128 EGY: 1 FIX: 0