Strojový kód, assembler, emulátor počítača Návrh architektúry hypotetického procesora Strojový kód Assemblerový jazyk Programovanie v assemblerovom jazyku: Lineárny program Vetvenie Cyklus Emulátor počítača Autor: Peter Tomcsányi, Niektoré práva vyhradené v zmysle licencie Creative Commons http://creativecommons.org/licenses/by-nc-sa/3.0/
Návrh architektúry hypotetického procesora Náš hypotetický procesor je 8-bitový. Má päť 8-bitových registrov Aj adresy do pamäte sú 8-bitové, pamäť môže mať teda maximálne 256 bajtov. Najnižší bit registra F sa nazýva bit Z, určuje, že porovnávané čísla boli rovnaké alebo že výsledok aritmetickej operácie bol nula. Ďalší bit registra F sa nazýva bit G, určuje, prvé z porovnávaných čísiel bolo väčšie než druhé. Ostatné bity registra F nemajú žiadny význam
Návrh strojového kódu Prvý Druhý Assemblerový bajt bajt zápis 00 NOP 01 n LDA n 02 n STA n 03 n ADD n 04 n SUB n 05 adr JMP adr Skoč na adresu adr Význam Neurob nič Prenes bajt z adresy n do registra A Prenes bajt z registra A na adresu n Pripočiítaj k A hodnotu z adresy n Nastav bit Z: keď je výsledok nula tak 1, inak 0 Odčítaj od A hodnotu z adresy n, Nastav bit Z: keď je výsledok nula tak 1, inak 0 Nastav bit G: keď je A neznamienkovo väčšie než obsah adresy n tak 1, inak 0 06 n CMP n Nastav bit Z: keď je A rovné obsahu adresy n tak 1, inak 0 07 08 FF adr adr JNE adr JG adr HALT Ak je bit Z v reg. F rovný 0, tak skoč na adresu adr Ak je bit G v reg. F rovný 1, tak skoč na adresu adr Zastav procesor x DATA x Pseudoinštrukcia - ulož do výsledného programu číslo x Prvý program v strojovom kóde Adresa Strojový kód Assemblerový zápis 00 01 05 LDA 5 02 03 06 ADD 6 04 FF HALT 05 02 DATA 2 06 03 DATA 3 Čo bude v registri A keď procesor zastaví? Symbolické vyjadrenie adries odbremení programátora od zisťovania ich číselnej hodnoty: HALT X: DATA 2 Y: DATA 3 Assemblerový jazyk sa nazýva aj Jazyk symbolických adries
Vykonávanie inštrukcií riadiacou jednotkou Konkretizácia pre navrhnutý procesor 1. Vyber inštrukciu z pamäti z adresy ktorá je v registri IP a umiestni ju do registra I. 2. Zvýš obsah registra IP o 1. 3. Ak inštrukcia potrebuje operand z pamäti (ako vstup alebo výstup), tak vyber jeho adresu z adresy ktorá je v registri IP, umiestni ju do registra Adr a zvýš register IP o 1. 4. Vykonaj inštrukciu. Pritom, ak treba, použi operand z adresy, ktorá je v registru Adr. 5. Ak inštrukcia ukladá výsledok do pamäti, tak ho ulož do pamäti na adresu, ktorá je v registri Adr. 6. Pokračuj znova krokom 1.
Úloha 1 Napíšte program v strojovom kóde, ktorý vypočíta 2*X+4*Y, kde X a Y sú uložené v bajtoch za programom. Program najprv zapíšte v assemblerovom zápise, potom ho preveďte do strojového kódu. ADD X HLT X: DATA 1 Y: DATA 2 00 : 01 0D 02 : 03 0D 04 : 03 0E 06 : 03 0E 08 : 03 0E 0A : 03 0E 0C : FF 0D : 01 0E : 02 Dá sa to naprogramovať na menej inštrukcií?
Úloha 2 Čo spraví tento program? Čo bude na jeho konci v X, Y a v registri A? CMP Y JG Koniec STA Pom LDA Y STA X LDA Pom STA Y Koniec: HALT X: DATA 3 Y: DATA 4 Pom: DATA 0 A = X if A > Y: pass else: Pom = A X = Y Y = Pom A = X A = X if A <= Y: Pom = A X = Y Y = Pom A = X
Úloha 3 Čo spraví tento program? STA N Cyklus: LDA Y ADD Vysl STA Vysl LDA N SUB Jedna STA N JNE Cyklus LDA Vysl HALT X: DATA 3 Y: DATA 4 Vysl: DATA 0 N: DATA 0 Jedna: DATA 1 Pre niektorú hodnotu X ale nebude fungovať správne. Opravte program.
Jednoduchý emulátor strojového kódu Emulátor je program, ktorý vykonáva inštrukcie strojového kódu konkrétneho (hypotetického alebo skutočného) procesora a simuluje prácu celého počítača. Náš jednoduchý emulátor slúži predovšetkým ako ukážka toho, čo sa deje vo vnútri procesora, teda aké úlohy plní riadiaca jednotka. Poslúži aj na vysvetlenie vzťahu strojového kódu a assemblerového jazyka. Naprogramoval som ho v Pythone. Niektoré vlastnosti Pythonu, ktoré som využil: čísla možno zapisovať aj v dvojkovej alebo aj v šestnástkovej sústave: x = 0b0101 y = 0xFE Python pozná logické operácie s číslami rovnako, ako C: print(x & y) print(x y)
Jednoduchý emulátor strojového kódu (2) Kompletný program nájdete na: http://edi.fmph.uniba.sk/~tomcsanyi/interpreterpython.zip def interpretuj(kod): pam = kod+[0]*(256-len(kod)) # doplnenie pamäte do 256 pc = 0; a = 0; f = 0 # počiatočné nastavenie while True: i = pam[pc]; pc = (pc+1)%256 if i == 0: # NOP neurob nič pass elif i == 1: # LDA adr = pam[pc]; pc = (pc+1)%256 a = pam[adr] elif i == 2: # STA adr = pam[pc]; pc = (pc+1)%256 pam[adr] = a elif i == 3: # ADD elif i == 7: # JNE adr = pam[pc]; pc = (pc+1)%256 if f & 1 == 0: pc = pam[pc] a =(a+pam[adr]) % 256 else: pc = (pc+1)%256 if a == 0: f = f 1 elif i == 8: # JG else: f = f & 0b11111110 elif i == 4: # SUB adr = pam[pc]; pc = (pc+1)%256 a =(a-pam[adr]) % 256 if a == 0: f = f 1 else: f = f & 0b11111110 elif i == 5: # JMP pc = pam[pc] elif i == 6: # CMP adr = pam[pc]; pc = (pc+1)%256 if a == pam[adr]: f = f 1 else: f = f & 0b11111110 if a > pam[adr]: f = f 2 else: f = f & 0b11111101 skúste: interpretuj([1,5,3,6,255,2,3]) if f & 2 == 1: pc = pam[pc] else: pc = (pc+1)%256 elif i == 255: break else: raise Exception('Neznáma inštrukcia'+ str(i)) return a