SimHYMN mikroprocesszor szimulátor

Fejezetek


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:

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