Operácie

ZPOC 9: Základy programovania v strojovom kóde

Zo stránky SensorWiki

Tieto jednoduché programy budeme analyzovať v simulátore procesora 8080. Pri práci je dobrou pomôckou tento ťahák s výberom inštrukcií. Obsluhu simulátora sme vysvetlili na cvičeniach, preto tu nájdete len tento stručný obrázok s opisom.


Časť I.

Nulovanie pamäťového miesta

Vynulujte obsah pamäťového miesta 0010h, do ktorého sme vložili naschvál nejaké číslo (55h), aby ste vedeli skontrolovať, že program naozaj danú pamäťovú bunku vynuluje. Obsah pamäte môžete meniť aj ručne.

V prvom stĺpci je intuitívne riešenie, na ktoré asi prídete hneď - má dĺžku 5 Bajtov a trvá 20 strojových cyklov. V druhom stĺpci je profesionálnejšie riešenie, ktoré je kratšie (4B, 17T) a aj nastaví príznaky. V treťom stĺpci je riešenie pomocou pseudoinštrukcie EQU, ktorá zjednoduší a sprehľadní programovanie. Porovnajte.

POZN.: toto sú programy napísané pre porovnanie vedľa seba, do simulátora musíte napísať len jeden zo stĺpcov, takže Copy/Paste odtiaľto vám nebude fungovať!

                              myData  equ 0010h
  org 0010h       org 0010h           org myData
  db 55h          db 55h              db 55              ; nejake data aby sme mali co vymazat
             
  org 0000h       org 0000h           org 0000h          ; program uloz od 0000h
  mvi a,00h       sub A               sub A              ; najprv vynulujem akumulator   sub A: A <- A-A = 0
  sta 0010h       sta 0010h           sta myData         ; a potom ho presuniem do pamäte     
  hlt             hlt                 hlt                ; stop, koniec


Presuny sem a tam

Tento program nerobí nič užitočné, len presúva data hore dole pomocou rozličných inštrukcií. Program je tu zámerne aj so strojovým kódom a adresami, takže sa nedá Copy/Paste do simulátora. Je to tak preto, že kopírovaním sa nič nenaučíte, je potrebné ten program naozaj napísať.

0000                          .ORG   0000h   ; tu hovorime, ze program zacne od adresy 0

0000   3E 07                  MVI   A,07h   ; A = 07h - uloz do akumulatora cislo 7
0002   47                     MOV   B,A     ; B = A   - obsah akumulatora skopiruj aj do B
0003   4A                     MOV   C,D     ; C = D   - neviem co je v D, ale skopiruj to do C
0004   32 10 00               STA   0010h   ; A = [0010] - do akumulatora skopiruj to co je v pamati na adrese 0010
0007   3E 00                  MVI   A,00h   ; A = 0, mozeme nahradit aj kratsim SUB A - cim vynulujeme A
0009   32 11 00               STA   0011h   ; to je vlastne MOV [0011],A cize presun (skopiruj) to co je v A do pamate
000C   3A 10 00               LDA   0010h   ; a toto je vlastne MOV A, [0010], cize presun z pamate do A
000F   76                     HLT

Súčet dvoch 8-bitových čísel

Spočítajte dve 8-bitové čísla v pamäti. Prvý aj druhý sčítanec sú uložené v pamäti [0010h] a [0011h], výsledok chceme vrátiť tiež do pamäte za oba sčítance, teda na adresu [0012h].

Odskúšajte pre rozličné vstupné data. Ako vieme, že výsledok je OK? Skúste aj také čísla, ktorými prekročíte rozsah. Čo sa stane?

Po preklade spočítajte koľko bajtov zaberajú obe riešenia a koľko SC spotrebujú.

0010                          ORG 0010H   
0010   02 03 00               DB  02H,03H,00H    ; tri cisla v pamati, tretie je 0 rezervovana pre vysledok
   
0000                          ORG 0000      
0000   3A 0D 00               LDA  0010H         ; do Akumulatora prve cislo z adresy 0010
0003   47                     MOV  B,A           ; presun zatial do B
0004   3A 0E 00               LDA  0011H         ; do Akumulatora druhe cislo z nasledujucej adresy
0007   80                     ADD  B             ; A <-- A + B
0008   32 0F 00               STA  0012H         ; vysledok odloz na nasledujucu adresu 
000B   76                     HLT

Tu je nepovinná ukážka, ako sa to dá spraviť aj celkom inak. Sú tam však inštrukcie, ktoré prekračujú rámec povinností na cvičeniach.

0010                          .ORG   0010H   
0010   02 03 00               DB   02H,03H,00H   

0000                          .ORG   0000   
0000   21 10 00               LXI   H,0010h     ; do HL adresu prveho cisla na adrese 0010
0003   7E                     MOV   A,M         ; do Akumulatora prve cislo z adresy {HL}
0004   23                     INX   H           ; HL <-- HL + 1
0005   86                     ADD   M           ; A <-- A + {HL}
0006   23                     INX   H           ; HL <-- HL + 1
0007   77                     MOV   M,A         ; uloz do pamate {HL}
0008   76                     HLT

Výmena

V pamäti sú za sebou uložené dve čísla. Vymeňte ich navzájom.

Pred spustením programu

0010 42
0011 55

Po vykonaní programu

0010 55
0011 42

Program môže vyzerať napríklad takto, znova je vo formáte, ktorý sa nedá Copy/Paste do simulátora. Viete prečo...

0010                          .ORG   0010h   
0010   42 55                  DB   42h,55h  
 
0000                          .ORG   0000h   
0000   3A 10 00               LDA   0010h     ; 1: precitaj do A z 010h
0003   47                     MOV   B,A       ; 2: odloz A do B
0004   3A 11 00               LDA   0011h     ; 3: precitaj do A z 011h
0007   32 10 00               STA   0010h     ; 4: to rovno zapisem do 010h
000A   78                     MOV   A,B       ; 5: vrat do A to z B
000B   32 11 00               STA   0011h     ; 6: zapis to do 011h
000E   76                     HLT             ; - hotovo


Precvičovanie

Preštudujte si nasledovný program:

            ORG     0000h 
            MVI     A,07h 
            MOV     B,A 
            MVI     A,03h 
            MOV     C,A 
            HLT

1 Aký bude obsah registra B po vykonaní celého programu?

2 Aký bude obsah registra A po vykonaní celého programu?


Preštudujte si nasledovný program:

            ORG     0040h 
            DB      01h,03h,05h,07h 

            ORG     0000h 
            LDA     0041h 
            MOV     B,A 
            LDA     0040h 
            ADD     B 
            STA     0042h 
            HLT

1 Aký bude obsah registra B po vykonaní celého programu?

2 Aký bude obsah registra A po vykonaní celého programu?

3 Aký bude obsah pamäťového miesta s adresou 0043h po vykonaní celého programu?

4 Aký bude obsah pamäťového miesta s adresou 0042h po vykonaní celého programu?


Preštudujte si nasledovný program:

            ORG     0040h 
            DB      01h,03h,05h,07h 

            ORG     0000h 
            LDA     0043h 
            MOV     B,A 
            LDA     0042h 
            SUB     B 
            STA     0041h 
            SUB     A 
            STA     0040h 
            HLT

1 Aký bude obsah registra B po vykonaní celého programu?

2 Aký bude obsah pamäťového miesta s adresou 0041h po vykonaní celého programu?

3 Aký bude stav príznaku Z (Zero) po vykonaní celého programu?

0
1

4 Aký bude obsah pamäťového miesta s adresou 0040h po vykonaní celého programu?



Časť II.

Programy, ktoré vidíte na tejto stránke sa nedajú jednoducho skopírovať do simulátora cez Copy/Paste, pretože si myslíme, že naučiť sa to dá len tak, že si tie programy sami napíšete krok za krokom aby ste vedeli čo ktorá inštrukcia robí.

Pri práci môžete používať ťahák s inštrukciami.


Vypočítajte dvojkový komplement čísla

V registri D máme čislo, ktorého dvojkový doplnok by sme chceli vypočítať. Výsledok uložíme do registra E.


                             .ORG   0000   
0000   16 03                  MVI   D,03h   
0002   7A                     MOV   A,D   
0003   2F                     CMA      
0004   3C                     INR   A   
0005   5F                     MOV   E,A   
0006   76                     HLT


Ako skúšku správnosti spravte naviac súčet výsledku a pôvodného čísla. Čo dostanete?

Test, či je číslo v pamäti nula

Pred delením musíme skontrolovať, či deliteľ na adrese 0020h náhodou nie je nula.

0020                          ORG   0020h   
0020   03                     DB   03h   

0000                          ORG   0000h   
0000   06 00                  MVI   B,00h      ; Do B si odlozime to co ideme testovat 
0002   3A 20 00               LDA   0020h      ; Do A nacitame cislo ktore ideme testovat
0005   B8                     CMP   B          ; test: je  Akumulator = B, teda 0?
0006   CA 0B 00               JZ    JeToNula   ; Ano, je to tak 
0009   00         NIEJENULA:  NOP              ; Tuto skoncime
000A   76                     HLT      
000B   00         JETONULA:   NOP              ; Nie, nie je to tak
000C   76                     HLT


Nájdi väčšie z dvoch čísel

V pamäti sú za sebou uložené dve čísla. Nájdi väčšie z nich a ulož ho na ďalšiu pozíciu v pamäti.

0010                          ORG   0010H   
0010   03 02 00                DB   02H,04H,00H   ; tri cisla v pamati, tretie je 0 rezervovana pre vysledok
0000                          ORG   0000   

0000   3A 10 00               LDA   0010h        ; do Akumulatora prve cislo z adresy 0010h
0003   47                     MOV   B,A          ; odlozime do B
0004   3A 11 00               LDA   0011h        ; do Akumulatora druhe cislo z adresy 0011h
0007   B8                     CMP   B            ; porovnaj B a Akumulátor
0008   D2 0C 00               JNC   HOTOVO       ; ak A > B skoc na HOTOVO:
000B   78                     MOV   A,B          ; v opacnom pripade presun do A druhu hodnotu
000C   32 12 00     HOTOVO:   STA   0012h        ; uloz vysledok na nasl. adresu
000F   76                     HLT

Inštrukcia CMP B spraví simulovaný rozdiel. Teda nastaví register F tak, ako keby bol obsah z B odpočítaný od obsahu A. Na rozdiel od inštrukcie SUB B však obsah Akumulátora ostáva nezmenený. Zhrnutie: Príznaky F sú nastavené nasledovne:

 Zero = 1   if   A = B
 Zero = 0   if   A ≠ B
Carry = 1   if   A < B
Carry = 0   if   A ≥ B

(A a B chápeme ako neznamienkové binárne čísla)

Poznámka: Ak by to niekoho zaujímalo, tak na presuny medzi pamäťou a procesorom existujú aj trocha efektívnejšie inštrukcie a postupy. Napríklad by to mohlo vyzerať takto:

0010                          ORG   0010H   
0010   03 02 00               DB   03H,02H,00H   ; tri cisla v pamati, tretie je 0 rezervovana pre vysledok

0000                          ORG   0000   
0000   21 10 00               LXI   H,0010h     ; do HL adresu prveho cisla na adrese 0010
0003   7E                     MOV   A,M         ; do Akumulatora prve cislo z adresy {HL}
0004   23                     INX   H           ; HL <-- HL + 1
0005   BE                     CMP   M           ; porovnaj {HL} a Akumulátor
0006   D2 0A 00               JNC   HOTOVO      ; ak A > {HL} skoc na HOTOVO:
0009   7E                     MOV   A,M         ; v opacnom pripade presun do A druhu hodnotu
000A   23           HOTOVO:   INX   H           ; HL <-- HL + 1
000B   77                     MOV   M,A         ; uloz vysledok na nasl. adresu
000C   76                     HLT

Vynásobenie dvoch čísel

Toto bude príklad na celkom jednoduché násobenie, nebudeme riešiť ani záporné čísla ani pretečenie.

Vynásobte dve čísla, uložené na adresách 0041h a 0042h. Výsledok uložte na 0040h.

0040                          ORG   0040h   
0040   03 04 00               DB   00h,03h,04h

0000                          ORG   0000h   
0000   06 00                  MVI   B,00      ; sem do B si budeme ukladat medzivysledky
0002   1E 00                  MVI   E,00      ; toto je nula, ktoru budeme testovat
0004   3A 40 00               LDA   0041h     ; prvy cinitel z pamati do A
0007   57                     MOV   D,A       ; odlozime si ho do D
0008   3A 41 00               LDA   0042h     ; druhy cinitel z pamati do A
000B   4F           SEM:      MOV   C,A       ; odlozime si ho do C - counter
000C   BB                     CMP   E         ; test: je uz Akumulator = E, teda 0?
000D   CA 18 00               JZ   KONIEC     ; ak ano, tak uz mame hotovo
                                              ; ak nie, pripocitame dalsi krat
0010   78                     MOV   A,B       ; v B mame medzivysledok, presunieme do A
0011   82                     ADD   D         ; pripocitame znova D
0012   47                     MOV   B,A       ; a odlozime medzisucet spat do B
0013   79                     MOV   A,C       ; teraz kukneme na pocitadlo
0014   3D                     DCR   A         ; odpocitame jednotku
0015   C3 0B 00               JMP   SEM       ; a pokracujeme znova

0018   78           KONIEC:   MOV   A,B       ; ak sme sa dostali az sem, tak medzivysledok
0019   32 42 00               STA   0040h     ; ulozime na spravne miesto do pamati
001C   76                     HLT


Pre hĺbavejších študentov sú určené nasledovné dva programy:

Spočítajte N čísel

Spočítajte N čísel so začiatkom na adrese 031h, pričom ich počet je na 030h. Výsledok uložte na 040h.

            .ORG    0030h 
            DB      03h,01h,02h,03h 
            .ORG    0000 

            LDA     0030H 
            MOV     C,A ; Initialize C-counter
            SUB     A ; sum = 0
            LXI     H,0031H ; Initialize pointer
BACK:       ADD     M ; SUM = SUM + data
            INX     H ; increment pointer
            DCR     C ; Decrement counter
            JNZ     BACK ; if counter 0 repeat
            STA     040H ; Store sum

            HLT     ; Terminate program execution

Nájdi maximum v bloku hodnôt.

V pamäti je uložený blok dát. Prvé číslo v bloku je počet dát, nasleduje neusporiadaná množina 8-bitových hodnôt.

            .org   0020H
            db     03h,02h,03h,01h   ; tri cisla = { 02, 03, 01 }
             
            .org   0000 
            lda    0020H 
            mov    C,A               ; Initialize counter
            sub    A                 ; Maximum = Minimum possible value = 0
            lxi    H,0021H           ; Initialize pointer
BACK:       cmp    M                 ; Is number > maximum
            jnc    SKIP              ; Yes, replace maximum
            mov    A,M 
SKIP:       inx    H 
            dcr    C 
            jnz    BACK 
            sta    0040H             ; Store maximum number

            HLT                      ; Terminate program execution



Precvičovanie II

Aj teraz tu máte pripravených niekoľko úloh na precvičenie na doma ako prípravu na písomku a upevnenie si znalostí.


1. Preštudujte si nasledovný program:

     ORG   0010h
      DB   51h,52h,53h,54h

     ORG   0000h  

     MVI   A,07h   
     MOV   B,A     
     MOV   C,D     
     STA   0010h   
     MVI   A,00h   
     STA   0011h   
     LDA   0012h   
     HLT

1 Aký bude obsah registra B po vykonaní celého programu?

2 Aký bude obsah registra A po vykonaní celého programu?

3 Aká hodnota bude po vykonaní celého programu na adrese 0010h?

4 Aká hodnota bude po vykonaní celého programu na adrese 0013h?


1. Preštudujte si nasledovný program:

            ORG   0020h   
             DB   XXh   

            ORG   0000h   
            MVI   B,00h      
            LDA   0020h      
            CMP   B          
            JNZ   SKOK
            MVI   B,02h
            HLT      
SKOK:       MVI   B,04h             
            HLT

1 Ak na zvýraznenom riadku 2 namiesto XX dosadíme 03, aký bude obsah registra B po vykonaní celého programu?

2 Ak na zvýraznenom riadku 2 namiesto XX dosadíme 03, na ktorom riadku program skončí?

3 Ak na zvýraznenom riadku 2 namiesto XX dosadíme 0, aký bude obsah registra B po vykonaní celého programu?

4 Ak na zvýraznenom riadku 2 namiesto XX dosadíme 0, na ktorom riadku program skončí?


Domáca úloha

Naprogramujte postupne zadané úlohy. Riešte ich postupne a spájajte ich do jedného komplexného programu. Ak si myslíte, že váš program je už hotový (alebo ak už viac neviete spraviť), vyplňte v Classroome formulár, do ktorého vyplníte stav registrov v ktorom ste skončili.


Najprv do pamäte na adresy 70h až 74h vložte hodnoty zodpovedajúce ASCII kódom prvých piatich písmen vášho krstného mena. Použite všetky písmená veľké
Napríklad pre mňa by obsah pamäte vyzeral takto

 0068 00 00 00 00 | 00 00 00 00
 0070 52 49 43 48 | 41 00 00 00
 0078 00 00 00 00 | 00 00 00 00
  1. Skopírujte (presuňte) obsah pamäťového miesta 71h na adresu 72h.
  2. Na adresu 75h vložte hodnotu 1 (01b, 1 desiatkovo, 01h, nie ASCII).
  3. Vypočítajte dvojkový doplnok z čísla uloženého na adrese 73h a výsledok uložte do 74h
  4. Odčítajte od 71h obsah 72h a výsledok zapíšte späť do 71h
  5. Sčítajte obsah pamäťových miest 71h a 75h a výsledok uložte do 72h
  6. Sčítajte obsah pamäťových miest 73h a 74h a výsledok uložte do 73h


Keď skončíte, vložte do formulára v Classroome odpoveď na otázku, aký bude na konci, po vykonaní všetkých inštrukcií, obsah v pamäti na adresách 70h až 73h a aký bude stav príznakov Z (Zero) a P (Parity) v registri F.

[70] = ?
[71] = ?
[72] = ?
[73] = ?
 
Flag Z = ?
Flag P = ?


Poznámka: Ak budete ASCII hodnoty vkladať do pamäte pomocou pseudoinštrukcie DB, dávajte pri simulácii pozor, pretože tieto hodnoty sa tam vložia len raz, pri zapnutí emulátora (F10). Ak spustíte program druhý raz, napríklad po stlačení RST, v pamäti ostanú hodnoty tak, ako ste ich tam zanechali. Ak chcete mať znova vložené správne hodnoty, musíte sa prepnúť do editora a späť.



Linky