Ú-3
Styk mikropočítača s prostredím

 
 
 
Programovanie v Assembleri
 
 µ
Použitie assemblera
   
q
Logická organizácia programu v jazyku assemblera
   
q
Postup pri vývoji programu
 
µ
Pseudooperátory Assemblera
   
q
Direktívy týkajúce sa segmentov a procedúr
   
q
Pseudooperátory týkajúce sa dát
   
q
Pseudooperátory týkajúce sa externých odkazov
 
µ
Pseudooperátory týkajúce sa výpisu programu
 
µ
Operátory pre rôzne operácie
 
µ
Príklady použitia assemblera a linkera
   
q
Príklady so štandarným spôsobom deklarovania segmentov
   
q
Príklady skráteného zápisu segmentov v modeli small
   
q
Príklady objasňujúce atribúty EXTRN a PUBLIC
 
 µ
Koncepcia prenosu dát do podprogramov
 
 µ
Makroinštrukcie
   
q
Špecialne makrooperátory
   
q
Priklad knižnice - Macro.lib

Ďalšia doplnková literatúra:
 
 
F Gavin's Guide to 80x86 Assembly - asmtut.zip
  [http://www.strangecreations.com/library/assembly/tutor/asm1.htm]
F Assembler Tutorial (H.Perez +R. de Yong) - asmttrl.zip.
  [http://udgftp.cencar.udq.mx/ingles/tutor/Assembler.html]
F TheArt of Assembly Language Programming (Randall Hyde1996) - Pdfaoa.zip.
  [http://webster.cs.ucr.edu/Page_asm/ArtofAssembly/ArtofAsm.html]
   


 

µ
Použitie  Assemblera

F Assembler – obecné pojmy a charakteristika jazyka

q Logická organizácia programu v jazyku assemblera

Pri vývoji programu sa obvykle používa nasledovný postup:

  • Pomocou vhodného editora sa napíše postupnosť príkazov v súlade so syntaxom programovacieho jazyka, v uvedenom prípade v jazyku mnemonických skratiek inštrukcii procesora Intel. Tomuto textovému súboru sa pridá koncovka .asm a zapíše sa. Logickú organizáciu takéhoto programu možno popísať niekoľkými vnorenými časťami: Napríklad:
 
1 úroveň: všeobecné záhlavie .  Code  segment  
            assume: Cs: Code
  2 úroveň: záhlavie procedúry Beep proc  
    3 úroveň: vstup kódu   mov dl, 7
            mov ah, 2
      4 úroveň: volanie obsluhy   int 21H
            mov ax, 4C00H
      4 úroveň: volanie obsluhy   int 21H
  2 úroveň: koniecprocedúry Beep endp  
1 úroveň: koniec záhlavia Code Ends  
            END Beep


q Postup pri vývoji programu: editovanie, kompilácia, linkovanie

Po napísaní textového tvaru postupnosti jednotlivých inštrukcii programu je výsledkom textový súbor.asm. Ďalší postup je nasledovný:

  • Pomocou vhodného kompilátora, v uvedenom prípade pomocou programu assembler, resp. jeho varianty fy Borland tasm.exe sa vykoná preklad do objektívneho kódu s koncovkou .obj. Poprípade sa súčastne vykoná aj listing programu. Napríklad pre súbor jano.asm:
 
    tasm/l/n jano.asm

  • Program linkera (napríklad tlink.exe) sa pospájajú jednotlivé moduly procedúr, preložené do objektívneho formátu a vytvorí sa spustiteľný súbor .exe. Poprípade ak treba sa ešte prekonvertuje tento súbor na tvar súboru .com. Napríklad pre jeden súbor jano.obj (s potlačením výpisu .map):
 
    tlink/x jano.obj

Poprípade niekoľkých modulov (jano.obj, data1.obj, data2.obj), ktoré majú ako hlavný program jano.obj:

 
    tlink/x jano data1 data2 

  • Prevod súboru.exe na súbor.com možno uskutočniť:
 
  exe2bin jano jano.com (ak sa neuvedie .com tak dosadí .bin) 

alebo priamo v jednom kroku pomocou linkera:

 
  tlink/t jano.obj 

  • Pomocou odlaďovacieho a testovacieho programu debugger sa odstránia chyby a prekrokovaním sa overí správna funkčnosť. Napríklad:
 
    debug jano.com
   alebo: debug jano.exe


Podmienený preklad

Po preklade zdrojového súboru kompilátorom vznikne jeden alebo niekoľko .OBJ súborov, ktoré sa násladne spoja do jedného programu pomocou zostavovacieho súboru (linkeru). Mnohokrát sa zložitejšie programy píšu tak, že obsahujú ladiace časti ako sú pomocné výpisy, funkcie uľahčujúce ladenie, napr. tak, že kontrolujú medze poli atď. Po odladení programu však nastáva typický problém - ako tieto už nepotrebné informácie z odladeného programu odstrániť. Aby sa to nemuselo odstraňovať pracne ručne (s rizikom, že si zmažeme potrebné časti programu) určíme preprocesoru, ktoré časti programu sa majú prekladať podmienene  (podmienený preklad). To znamená, že pri vytváraní programu označíme určité časti ako podmienečne prekladané: pri ladení ich potom prekladáme a po odladení ich už nepoužívame. Ladiace časti sú tak trvalou súčasťou zdrojového súboru ale voliteľnou súčasťou programu. Preprocesor tak na základe príslušného podmieneného príkazu (if, else a pod.) vypustí tieto časti.

Pamätový modul popisuje spôsob adesovania dát v pamäti a tiež charakterizuje veľkosť programu na základe počtu segmentov. Použitím vhodného pamäťového modulu možno zjednodušiť napríklad deklarovanie segmentov a pod. Používajú sa nasledovné moduly:

  • Tiny - kód a dáta sú v rozsahu jedného 64kB segmentu.
  • Small - kód uložený v jednom 64kB segmente a data v druhom 64kB segmente.
  • Compact - kód uložený v jednom segmente a data sú vo viacerých segmentoch.
  • Medium - kód je vo viacerých segmentoch a dáta sú v jednom segmente.
  • Large a Huge - kód je vo viacerých segmentoch a dáta sú vo viacerých segmentoch.


 
µ
Pseudooperátory Assemblera

Pseudooperátory (inštrukcie, direktívy) riadia preklad assemblera a nie činnosť mikroprocesora. Týkajú sa:

  1. dát, segmentov a procedúr, externých odkazov;
  2. riadenia výpisu listingu;
  3. operácii.

 
1a. Direktívy týkajúce sa segmentov a procedúr

Typický program v assembleri má štruktúru, v ktorej pseudodirektívy:

F SEGMENT a ENDS vymedzujú hranice segmentu.
 
 
  Syntax:  Name_Seg SEGMENT  [align][combine][use][‘clas’]

  • Name_Seg - meno, ktoré funguje ako náveštie.
  • Align - špecifikuje hranice pamäti, kde by sa mal segment začínať. Platné zarovnávanie je:
    • Byte - použije adresu nasledujúceho bajtu.
    • Word - použije adresu na hranici 2 bajtov (slovo).
    • Dword - použije adresu na hranici nasledujúcich 4 bajtov (2*slovo).
    • Page - použije adresu na hranici nasledujúcej stránky (=256 bajt).
    • Para - použije adresu nasledujúceho paragrafu (= 16 bajt) - implicitné.
  • Combine - riadi spôsob ako sa segmenty rovnakého mena z rôznych modulov budú vzájomne kombinovať pri zlinkovaní.
    • At - umiestni segment na špecifikovanú adresu.
    • Common - umiestni segmenty na rovnakú adresu.
    • Private - nekombinuje segment so žiadnym iným segmentom.
    • Public - pospája za sebou všetky segmenty rovnakého mena do jedného segmentu, ktorého dlžka bude súčtom dlžok segmentov.
    • Stack - pospája za sebou všetky segmenty rovnakého mena do jedného segmentu, ktorý linker inicializuje ako zásobník SS:SP.
  • Use - špecifikuje implicitnú veľkosť segmentu, napríklad use16, use32 = veľkosť pamäte.
  • Class - riadi zaraďovanie do spojitého bloku pamäte, nezávisle od poradia v programe. Clastype je v apostrofoch a špecifikuje grupu do ktorej sa priradí segment. Napríklad:
 
  Name_Seg Segment para stack ‘stack’

F  ASSUME - pseudoinštrukcia, oznamujúca assembleru, že uvedený segmentový register bude použitý na adresovanie. Umiestňuje sa hneď za pseudodirektívu segment a platí do ohlásenia iného výskytu assume.

 
  Syntax: Segmentový_reg:meno_reg

Na základe tohto priradenia vie assembler ako (pomocou ktorého segmentového registra) zabezpečí prístup k premenej.

F Tvar príkazu. Syntax príkazu má 4 polia:

 
  [Náveštie:] Mnemonický kód  [Operand] [;komentár]

Náveštie môže pozostávať max z 31 znakov. Napríklad:

 
  GET_count: mov  cx,dx ;inicializácia

F PROC / ENDP - definuje začiatok / koniec procedúry.

  • Blízka adresa (NEAR) určuje pamäťové miesto vo vnútri segmentu.
  • Vzdialená adresa (FAR) sa vzťahuje na objekt vo fyzickej pamäti = napríklad v oblasti 32 bit adresy. Near a Far sa vzťahuje aj na Jmp, Call = od neho závisí tvar RET.= Pri Near Call sa ukladá len IP, pri Far Call CS:IP.
Assembler po preložení programu si označí (pozri napríklad výpis Pgo1.lst):

 
  r -  posunutie (offset) vo vnútri modulu 
  s -  segment pre symboly vo vnútri modulu
  e -  offset na externý symbol
  + -  cieľový kód, ktorý bol vynechaný.

F END- oznamuje assembleru koniec zdrojového programu. Ak za nim uvedie meno náveštia, alebo meno procedúry END [náveštie alebo vstup] bude sa výsledný program začínať od tohto bodu.


 
1b. Pseudo operátory týkajúce sa dát

F LABEL(náveštie ) - symbol označujúce miesto v kóde. Náveštie môže špecifikovať near / far symboly alebo procedúry. Implicitne, bez uvedenia je near. Je to identifikátor umožňujúci priradiť výrazu symbolické meno, napríklad odvolať sa na adresu buniek pomocou náveštia. Napríklad:

  • 16 bitový posuv pomenovaný náveštím:
 

HERE_NEAR: DW HERE
  • náveštie na charakterizovanie segment offsetu :
 
    sulf Label far ;ako far
  sulf: mov ax,bx ; ako near
  • náveštie na charakterizovanie premenej:
 
  bary Label byte (resp. word)
  • náveštie na charakterizovanie tabuľky s údajmi v tvare bajtov, ktoré však majú byť interpretované ako slova:
 
  Textwords: LABEL word  
    BYTES DB 64 DUP (?)

F DEFINE- definuje a inicializuje premenné , napríklad na rezervovanie pamäti pre dáta.
 
 
DB - bajt  napríklad B_max DB 255;
DW - slovo  napríklad B_max  DW 32785;
DD - double word      
DQ - quad word - real      
DT - 10 byte BCD      
DUP - duplicate -  opakovanie operandu dát.
Napríklad:  
 
 
  B_TAB DB 4 DUP (0),8   
    DB 3 DUP (63),  
    DB 12 DUP (?) ;=len rezervuje, nemení obsah

u Priklad rôznych typov údajov 
 
 
  DSEG SEGMENT PARA PUBLIC "DATA"
  23   Db 23h  ;bajt 23
  01 02 03 04   Db 1,2,3,4  ;4x bajt postupne
  5 ??   Db ?  ;ponecha obsah - rezerva
  19*(??)   Db 25 dup(?)  ;rezervuje 25 bajt zachova obsah
  11*(31)   Db 17 dup (31h)  ;zaplni 17 x 31h
  1E*(01 02 03 04)   Db 30 dup (1,2,3,4) ;zaplni 30 x 1,2,3,4
  1234   Dw 1234h  najprv ulozi LSB potom MSB
  03*(5678)   Dw 3 dup (5678h)  ;3 x zopakuje
  ????   Dw ?  ;slovo rezervuje
  03E8*(??) mem  Db 1000 dup(?)  ;rezerva
  54 68 69 73 20 69 73 + Sprava Db "This is a message",10,13 ;text +LF,CR
  20 61 20 6D 65 73 73 +      
  61 67 65 0A 0D      
  DSEG ENDS    

F EQU - jenorázovo priraďuje numerickú náhradu, definuje reťazec, alebo náhradné náveštie.
Napríklad:   
 
  K EQU 1024  
  speed EQU RATE ; synonymum
  TABLE EQU DS:[BP][SI] ;meno alebo kombinácia adries

F = (zhodnosť) - len pre číselné hodnoty. V programe možno viackrát použiť.
 
 
  Napríklad: const = 56
    CR = 0DH

Číselné konštanty bývajú doplnené D, H, B, Q = v závislosti od použitej číselnej sústavy.


 
1c. Pseudo operátory externých odkazov

F EXTRN- pseudoinštrukcia charakterizujúca externý symbol. Napríklad typ dát:
 
 
  EXTRN symbol1: byte,  Symbol2: word

Na základe takejto deklarácie môže linker doplniť správnu efektívnu adresu. Platí predpoklad, že ak je EXTRN uvedené v nejakom segmente, sú aj zavedené symboly deklarované v rovnakom segmente. Napríklad procedúra output_sbr a symbol output_znak, ktorý reprezentuje reprezentujúci adresu bunky, v ktorej je premená:   
 
  EXTRN output_sbr:near output_znak:byte


 
2. Pseudo operátory týkajúce výpisu (listingu)

Na začiatku súboru.asm sa obvykle kvôli listingu nachádzajú pseudooperátory:   
 
F PAGE
 

 

[počet riadkov] [počet stlpcov] - Slúži na nastavenie počtu riadkov a ich dĺžky na strane (od 10 - 235 riadkov, šírka od 60 do 132 implicitne 60; pre komprimované písmo treba 132).
F TITLE - max 60 znakov ktoré tlačí na záhlavii každej strany v 2 riadku.
F SUBTTL - doplnok k záhlaviu na 3 riadku každej vytlačenej strany.


 
3.
Operátory pre rôzne operácie

umožňujú vytvoriť súbor výrazov, ktoré môžu byť použité ako operand inštrukcie alebo direktívy. Jedná sa o rôzne typy operátorov, napríklad:   
 
a. 
aritmetické (napríklad +,-,*,());
b.
logické (napríklad and, or);
c. 
vzťahové (napríklad DUP);
d. 
vracajúce hodnotu s informáciou (napríklad SEG, OFFSET, $,).

Napríklad:
F $ - vracia aktuálnu hodnotu počitadla adresy.
F SEG - vracia adresu začiatku segmentu.
F OFFSET - vracia adresu relatívneho posunutia (offsetu).
F TYPE - vracia 1 ak DB, 2 ak DW, resp 1 ak NEAR a 2 ak FAR.
F LENGTH - vracia počet jednotiek ( byte, word) v rezervovanej časti pamäte, napríklad rezervovanej s použitím DUP.
 
 
e. 
prisvojujúce (napríklad PTR, ORG )

F PTR - funkcia slúžiaca na zmenu pôvodného atribútu výrazu. Napríklad ak chcem mať prístup k bajtom v tabulke, ktorá je slovne organizovaná. PTR - určuje veľkosť ukazovateľa alebo dát samotných, na ktoré ukazuje symbol adresy. Pre mnemonickú inštrukciu obracajúcu sa k pamäti nestačí uviesť adresu ale k vygenerovaniu správneho kódu treba poznať aj typ dat:   
 
Syntax typ_dat PTR symbol_predstavujuci_adresu_
Napríklad ak ide o slovo: INC WORD PTR DS:[2D6H.]

Tento tvar sa, može sa objaviť pri odassemblovaní kódu programu pomocou programu debug. 
F ORG - slúži na nastavenie počitadla aktuálneho segmentu. Napríklad pre subor.com:
 

    .Model small    
    .Code    
    ORG 100H  
  Start: jmp Začiatok ;tu sa začína kód programu
    ....   ;pokračovanie.


 
µ Príklady použitia assemblera a linkera

 
 
1) Príklady so štandarným spôsobom deklarovania segmentov

Demo_A1 (Pgo1.asm)

Z programátorskej stránky príklad ilustruje použitie operandov z pamäti a štandardné inicializovanie segmentu DS pre návrat do DOS pomocou RET = predpríprava DS:0 v úvode programu.

Z funkčnej stránky procedúra prečíta 4 bajty z adresy SOURCE v pamäti a uloží ich v opačnom poradí do pamäti od adresy DEST. Slúži aj ako príklad listingu (povšimnite si symboly s, r, procedura far ) a ako príklad odlaďovania pomocou debuggera ( kontrola obsahu pamäti spojenej so segmentami CS, DS, SS).

Demo_A1: (Všetky programy a listingy sú bez slovenskej diaktriky.)
 
 
  page,132      
  title pgo1.asm
  subttl Vstup retazca znakov/Vystup v opacnom poradi
  STACKs  SEGMENT STACK "STACK"  PARA 
    DB 64DUP ("STACK ")  
  STACKs  ENDS    
  DSEG SEGMENT  PUBLIC "DATA"  PARA 
  SOURCE DB 10h,20h,30h,40h  ;zakladna tabulka
  DEST  DB 4 DUP (?) ;sem sa prepise DB
  DSEG   ENDS  
         
  CSEG SEGMENT  PUBLIC "CODE"  PARA 
         
  OUR_PROG  PROC  FAR   ;zaciatok procedury
    ASSUME CS:CSEG, DS:DSEG, SS:STACKs
  ;Ulozit do zasobnika zakladne parametre, aby sa program mal kam vratit
    PUSH DS ;ULOZENIE NAVRAT ADRESY
    MOV  AX, 0 ;VYNULOVANIE (A)
    PUSH  AX ; ULOZENIE 0 POSUNUTIA
  ;Inicializovat adresu segmentu dat
    MOV  AX, DSEG ;Nastavit DS
    MOV DS, AX  
  ;Priradit elementom tabulky DEST nulovu zakladnu hodnotu
    MOV  DEST, 0 ;1 BAJT
    MOV  DEST+1, 0 ;2 BAJT
    MOV  DEST+2, 0  ;3 BAJT
    MOV  DEST+3, 0  ;4 BAJT
  ;Prekopirovat tabulku SOURCE do tab DEST v opacnom poriadku
    MOV AL, SOURCE ;copy 1BAJT
    MOV DEST+3, AL  
    MOV  AL, SOURCE+1 ;2 BAJT
    MOV  DEST+2, AL  
    MOV AL, SOURCE+2 BAJT
    MOV DEST+1, AL  
    MOV AL, SOURCE+3 ;4 BAJT
    MOV DEST, AL  
    RET    
  OUR_PROG ENDP   Koniec nasej proc.
  CSEG  ENDS    
  END  OUR_PROG ;oznam kde je zaciatok

PGO1.lst = vypis
 
  subttl Vstup retazca znakov/Vystup v opacnom poradi 
  5 0000  STACKs SEGMENT PARA STACK "STACK"

6 0000 40*(53 54  DB 64 DUP ("STACK ")


41 43 4B 20+
   7 20 20)      
  8 0200 STACKs ENDS
  9      
  10 0000  DSEG SEGMENT PARA PUBLIC "DATA"
  11 0000 10 20 30 40  SOURCE DB 10h,20h,30h,40h  
  12 0004 04*(??)  DEST DB 4 DUP (?)  
  13 0008 DSEG ENDS
  14       
  150000 CSEG SEGMENT PARA PUBLIC"CODE"
  17 0000  OUR_PROG PROC FAR
  18  ASSUME CS:CSEG, DS:DSEG, SS:STACKs
  21 0000 1E    PUSH DS   
  22 0001 B8 0000    MOV AX, 0  
  23 0004 50    PUSH AX   
  25 0005 B80000s .!   MOV AX, DSEG ;Nastavit DS
  26 0008 8E D8    MOV DS, AX  
  28 000A C6 06 0004r 00   MOV DEST, 0 1 BAJT
  29 000F C6 06 0005r 00   MOV DEST+1, 0 ;2 BAJT
  30 0014 C6 06 0006r 00   MOV DEST+2, 0 ;3 BAJT
  31 0019 C6 06 0007r 00   MOV DEST+3, 0 ;4 BAJT
  33 001E A0 0000r.....!   MOV AL, SOURCE ; 1 BAJT
  34 0021 A2 0007r    MOV DEST+3, AL  
  35 0024 A0 0001r    MOV AL, SOURCE+1 ;2 BAJT
  36 0027 A2 0006r   MOV DEST+2, AL  
  37 002A A0 0002r   MOV SOURCE+2  ;3 BAJT
  38 002D A2 0005r    MOV DEST+1, AL  
  39 0030 A0 0003r   MOV AL, SOURCE+3 4 BAJT
  40 0033 A2 0004r    MOV DEST, AL  
  41 0036 CB    RET  
  42 0037    OUR_PROG   
  43 0037  CSEG ENDS  
  44  END OUR_PROG  

Všimnut si ....s a ....r za adresami,ktoré doplni LINK.
 
 
 
DEBUG pgo1.exe - niektoré zaujímavosti.
 
r Všimnut si nastavenie SP na 200 = rezerva 64x8=512=200H
AX=0000 BX=0000 CX=0247 DX=0000 SP=0200 BP=0000 SI=0000 DI=0000 
DS=13AD ES=13AD SS=13BD CS=13DE IP=0000 NV UP EI PL NZ NA PO NC 
13DE:0000 1E PUSH DS 
 
-t Všimut si zniženie (SP-2)
AX=0000 BX=0000 CX=0247 DX=0000 SP=01FE BP=0000 SI=0000 DI=0000 
DS=13AD ES=13AD SS=13BD CS=13DE IP=0001 NV UP EI PL NZ NA PO NC 
13DE:0001 B80000 MOV AX,0000 
 
-t
AX=0000 BX=0000 CX=0247 DX=0000 SP=01FE BP=0000 SI=0000 DI=0000 
DS=13AD ES=13AD SS=13BD CS=13DE IP=0004 NV UP EI PL NZ NA PO NC 
13DE:0004 50 PUSH AX 
-t Všimnut si že Data sa začinaju na 13DDH
AX=0000 BX=0000 CX=0247 DX=0000 SP=01FC BP=0000 SI=0000 DI=0000 
DS=13AD ES=13AD SS=13BD CS=13DE IP=0005 NV UP EI PL NZ NA PO NC 
13DE:0005 B8DD13 MOV AX,13DD 
-g36 Všimut si že pretože proc far dosadilo RETF
AX=1340 BX=0000 CX=0247 DX=0000 SP=01FC BP=0000 SI=0000 DI=0000 
DS=13DD ES=13AD SS=13BD CS=13DE IP=0036 NV UP EI PL NZ NA PO NC 
13DE:0036 CB RETF 
 
-dds:0 < -data-- <-opačne data
13DD:0000 10 20 30 40 40 30 20 10-00 00 00 00 00 00 00 00 . 0@@0 ......
-dss:0
13BD:0000 53 54 41 43 4B 20 20 20-53 54 41 43 4B 20 20 20 STACK STACK 
13BD:0010 53 54 41 43 4B 20 20 20-53 54 41 43 4B 20 20 20 STACK STACK 
 
13BD:01D0 53 54 41 43 4B 20 20 20-53 54 41 43 4B 20 20 20 STACK STACK 
13BD:01E0 53 54 41 43 4B 20 20 20-53 54 41 43 4B 20 20 20 STACK STACK 
13BD:01F0 53 54 00 00 00 00 36 00-DE 13 00 0E 00 00 AD 13 ST....6......
Tu konči zásobnik a začina sa DSEG
13BD:0200 10 20 30 40 40 30 20 10-00 00 00 00 00 00 00 00 . 0@@0 .....
Tu konči Dseg a začina Cseg = program
13BD:0210 1E B8 00 00 50 B8 DD 13-8E D8 C6 06 04 00 00 C6 ...P...........
13BD:0220 06 05 00 00 C6 06 06 00-00 C6 06 07 00 00 A0 00 ..............
13BD:0230 00 A2 07 00 A0 01 00 A2-06 00 A0 02 00 A2 05 00 ........

-u 0 36 výpis - všimnúť si ukazovateľ na bunku s bajtom BYTE PTR, pretože debugger nepozná označenie buniek použité v assemblovanom programe.
 
 
  13DE:0000 1E    PUSH DS
  13DE:0001 B80000  MOV AX, 0000
  13DE:0004 50    PUSH AX
  13DE:0005 B8DD13  MOV  AX, 13DD
  13DE:0008 8ED8 MOV  DS,AX 
  13DE:000A C606040000  MOV  BYTE PTR [0004], 00
  13DE:000F C606050000  MOV  BYTE PTR [0005], 00
  13DE:0014 C606060000  MOV  BYTE PTR [0006], 00
  13DE:0019 C606070000  MOV  BYTE PTR [0007], 00
  13DE:001E A00000  MOV  AL, [0000]
  13DE:0021 A20700  MOV  [0007], AL
  13DE:0024 A00100  MOV  AL, [0001]
  13DE:0027 A20600  MOV  [0006], AL
  13DE:002A A00200  MOV  AL, [0002]
  13DE:002D A20500  MOV  [0005], AL
  13DE:0030 A00300  MOV  AL, [0003]
  13DE:0033 A20400  MOV  [0004], AL
  13DE:0036 CB    RETF 

Bfig_3-2.asm

Všimnúť si v listingu rôzne spôsoby adresovania operandov.
 
 
  Turbo Assembler Version 1.01 15/10/92 11:26:14 Page 1
  BFIG32.ASM
  Fig.3.2 - Priklad rozneho adresovania
   
  1 0000                  CSEG SEGMENT
  2                     ASSUME CS:CSEG,DS:cSEG,SS:cseg
  3                  org 123h                              ;pre data
  4 0123 ????                opnd   dw ?
  5                  org 200h                             ;pre program
  6 ;
  7 0200   our_prog proc
  8 0200 43                    inc bx                                  ;inc register
  9 0201 FF 06 0123r      inc opnd                               ;inc pamati-priama adr
  10 0205 FF 07             inc word ptr [bx]                    ;inc pamat -nepriama adr
  11
  12 ;Adresa = base + priame posunutie, resp. priame posunutie + index
  13 0207 FF 87 0123r    inc [opnd+bx]                          ;posunutie+index
  14 020B FF 84 0123r    inc [opnd+si]                          ;to iste iny zapis
  15 020F FF 85 0123r    inc opnd + [di]
  16 0213 FF 86 0123r    inc [opnd] + [bp]
  17
  18 ;Adresa base (BX alebo BP s indexom (SI alebo DI)+posunutie=0
  19 0217 FF 00             inc word ptr [bx+si]                   ;base + index
  20 0219 FF 03             inc word ptr [bp]+[di]
  21
  22 021B FF 81 0123r   inc [opnd +bx+di]                     ;base+index+posunutie
  23 021F FF 82 0123r    inc opnd[bp][si]
  24
  25 0223   OUR_PROG ENDP
  26 0223              CSEG ENDS
  27                                 END OUR_PROG
   
  -u
  19FB:0200 43               INC BX 
  19FB:0201 FF062301    INC WORD PTR [0123] 
  19FB:0205 FF07           INC WORD PTR [BX] 
   
  19FB:0207 FF872301    INC WORD PTR [BX+0123]
  19FB:020B FF842301    INC WORD PTR [SI+0123] 
  19FB:020F FF852301    INC WORD PTR [DI+0123] 
  19FB:0213 FF862301    INC WORD PTR [BP+0123] 
   
  19FB:0217 FF00           INC WORD PTR [BX+SI] 
  19FB:0219 FF03           INC WORD PTR [BP+DI] 
   
  19FB:021B FF812301    INC WORD PTR [BX+DI+0123] 
  19FB:021F FF822301    INC WORD PTR [BP+SI+0123]

Bfig_3-9.asm

Príklad listingu, ktorý umožňuje porovnať implicitný spôsob adresovania dat (cez DS) s adresovaním cez ES a CS, v ktorých treba na odlíšenie použiť segment prefix.
 
 
BFIG39.ASM
Fig.3.9 - Priklad pouzitia segmentov na adresu v pamati
 
1 ;Segment definovane s posuvom vzdy +16 bit
2 0000     data segment public para
3 0000 01              var1 db 1                  ;Premenna v Data segmente
4 0001                 data ends
5
6 0000     buffer segment public para
7 0000 02              var2 db 2                 ;Premenna v Buffer segmente
8 0001                 buffer ends
9
10 0000     CSEG SEGMENT public para
11 0000 03             var3 db 3                ;Premenna v Code segmente
12
13                     assume cs:Cseg,ds:data,es:buffer
14
15 0001     Nas_prog proc          ;Fiktivny demonstracny program
16
17 0001 8C C8          mov ax,cs        ;Definovanie segmentov
18 0003 2D 0001        sub ax,1          ;o 10 bit nizsie je prisl adr dat
19 0006 8E C0          mov es,ax
20 0008 2D 0001        sub ax,1         ;o dalsich 16 bit nizsie je adresa
21 000B 8E D8          mov ds,ax
22 000D FE 06 0000r    inc var1          ;+1 do bajtu adresovaneho cez Dseg
23 0011 26:FE060000r   inc var2          ;+1 do bajtu adresovaneho cez Eseg
24 0016 2E:FE060000r   inc var3         ;+1 do bajtu adresovaaneho cez Cseg
25
26 001B      Nas_PROG ENDP
27
28 001B              CSEG ENDS
29                                 END Nas_prog
-r
AX=0000 BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=19EB ES=19EB SS=19FB CS=19FD IP=0001 NV UP EI PL NZ NA PO NC 
19FD:0001 8CC8 MOV AX,CS 
-t
AX=19FD BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 
DS=19EB ES=19EB SS=19FB CS=19FD IP=0003 NV UP EI PL NZ NA PO NC
19FD:0003 2D0100 SUB AX,0001 
-gd
AX=19FB BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 
DS=19FB ES=19FC SS=19FB CS=19FD IP=000D NV UP EI PL NZ NA PO NC 
19FD:000D FE060000 INC BYTE PTR [0000] DS:0000=01
-t
AX=19FB BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 
DS=19FB ES=19FC SS=19FB CS=19FD IP=0011 NV UP EI PL NZ NA PO NC 
19FD:0011 26 ES: 
19FD:0012 FE060000 INC BYTE PTR [0000] ES:0000=02
-t
AX=19FB BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 
DS=19FB ES=19FC SS=19FB CS=19FD IP=0016 NV UP EI PL NZ NA PE NC 
19FD:0016 2E CS: 
19FD:0017 FE060000 INC BYTE PTR [0000] CS:0000=03
 
-u 1 17
19FD:0001 8CC8 MOV AX,CS 
19FD:0003 2D0100 SUB AX,0001 
19FD:0006 8EC0 MOV ES,AX 
19FD:0008 2D0100 SUB AX,0001 
19FD:000B 8ED8 MOV DS,AX 
19FD:000D FE060000 INC BYTE PTR [0000] 
19FD:0011 26 ES: 
19FD:0012 FE060000 INC BYTE PTR [0000] 
19FD:0016 2E CS: 
19FD:0017 FE060000 INC BYTE PTR [0000] 
 
-dds:0 3f
19FB:0000 02 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ...
19FB:0010 03 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ....
19FB:0020 03 8C C8 2D 01 00 8E C0-2D 01 00 8E D8 FE 06 00 
19FB:0030 00 26 FE 06 00 00 2E FE-06 00 00 54 0A 83 C0 41 
-t
AX=19FB BX=0000 CX=003B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 
DS=19FB ES=19FC SS=19FB CS=19FD IP=001B NV UP EI PL NZ NA PO NC
19FD:001B 54 PUSH SP 
Az teraz bola vykonana instrukcia
-dds:20 3f
19FB:0020 04 8C C8 2D 01 00 8E C0-2D 01 00 8E D8 FE 06 00 
19FB:0030 00 26 FE 06 00 00 2E FE-06 00 00 54 0A 83 C0 41 

Bfig_4-26.asm

Program ilustruje rôzne typy JUMP a CALL:

  • relatívny (near- DW adresa),
  • absolutny (far-DD-adresa),
  • priamy (direct-DW adresa) a
  • nepriamy (indirect-DD adresa).
 
TITLE Priklad na relativny JUMP + CALL
page , 132
;Demo program ilustruje rozne typy CALL
;--------------------------------------------
far_      seg      segment 
          assume CS:far_seg
far_      label    proc far
nop
ret
far_      label    endp
far_      seg      ends
;---------------------------------
code      segment
          assume cs:code
indirect_ far  dd far_label
indirect_ near dw near_label
our_prog  proc near
call      near_label               ;Relativny CALL
call      far_ label               ;Absolutny CALL
call      indirect_near            ;Indirect near CALL
call      indirect_far             ;indirect far CALL
jmp start                          ;Skok na navestie start
our_      prog endp
near_     label proc near
ret
near_     label endp
 
;------------------------------------------
;Demo program ilustruje relativne posunutie pri JUMP
;-------------------------------------------
start:
jmp short label_one                ;Falosny skok
label_one:
jmp       label_two                ;Skok - short
label_two:
jmp       label_three              ;Skok - far
                                   ;pomocou ORG simuluje far
org 200h                           ;Sem skoci mimo segment
label_three:
start1:
jmp start1                         ;Skok na seba=stop
code ends
END       our_prog 

Bfig_4-28.asm

Program ilustruje použitie nepriamych adries z rozvetvovacej tabulky, ku ktorým sa pristupuje na základe indexu uloženého v AL. Skoková adresa závisí od zaciatocnej adresy tabulky Branch_Table a od posunutia, realizovaného (BX) = v danom prípade near adries DW vždy o 2 bajty = posuv o 0, 2, 4 bajty.
 
 
TITLE Priklad na rozvetvovaciu tabulku 
page , 132
Code SEGMENT 
     ASSUME CS:Code
;-----------------------------------------------
;Program sa rozvetvi podla (AL). Hodnota v AL sluzi ako
;rozvetvovaci index. Pri odladovani treba zadat (AL).
;----------------------------------------------
our_ prog proc 
sub  bh,bh                     ;(BL)<--0
mov  bl,al                     ;Rozvetv index do AL
shl  bx,1                      ;*2 pre slovo
jmp  CS:[BX+BRANCH_TABLE]      ;nepriame vetvenie
our_ prog endp
 
branch_table label word
     dw                        ;adresa SBR_PRVA
     dw                        ;adresa sbr_druha
     Dw                       ;adresa sbr_tretia
;.....
sbr_ prva    label near
     Dw 1122h
sbr_ druha   label near
     Dw 2233h
sbr_ tretia  label near
     Dw 4455h
CODE ENDS
END  OUR_PROG 

Demo_A2 (Bfig 6.12.asm) 

Príklad použitia direktívy Combine = AT na alokovanie segmentu od určitej adresy - v uvedenom príklade na adresu tabulky BIOS parametrov k bunke KB_FLAF = 417:0 (, kde sa ukladá informácia o stave pomocných klávesov - shift, ctrl, alt a pod.) a na adresu začiatku textovej videopamäte B800:0.

TITLE Bfig 6.12 Priklad Segment Location
 
 
DATA  Segment At 40h ; na 417H
  Org 17h  
kb_flag  Db ?  
caps_state  Equ 40h  
data  Ends    
       
Video Segment At 0b800h ;obrazovka
  Org 158  
indicator  Db ?  
video  Ends    
       
Code  SEGMENT    
  ASSUME  CS:Code  
CAPS  Proc FAR  
       
START:      
  Push  ds  ;Return address
  mov  ax, 0  
  push  Ax  
  mov  ax, data ;Data segment address
  mov ds, ax  
  ASSUME  ds:data  
  mov  ax, video ;Video segment address
  mov  es, ax  
  ASSUME  es:video  
display_caps:     : = vlastny program
    ....  
    ....  
Return: Ret   ;Return to DOS
       
Caps  Endp    
code  Ends    
  END caps  

Demo A_3 (Bfig39pn.asm)

Príklad použitia rôznych segmentov na adresovanie slov v rôznych častiach pamäte s využitím segmentov CS, DS, ES.

Výpis BFIG39PN.ASM:
 
2 0000 data_seg Segment  public  para  
3 0000 0001   ds_var Dw 1 ;Premenna v DS
4 0002 data_seg ends      
           
6 0000 extra_seg segment Public Para  
7 0000 0002   es_var Dw 2 ;Premenna v ES
8 0002 extra_seg ends      
           
10 0000 CSEG SEGMENT Public para  
11 0000 0003   cs_var dw ;Premenna v CS
 13   assume cs:Cseg, ds:data_seg, es:extra_seg
           
15 0002 Nas_prog  Proc far      
16 0002 06   Push es ;Navratova adresa   pre DOS  
17 0003 33 C0   Xor ax,ax      
18 0005 50   Push ax      
19 0006 B8 0000s   Mov ax,Data_seg ;Definovanie segmentov    
20 0009 8E D8   Mov ds,ax      
21 000B B8 0000s   Mov ax,Extra_seg      
22 000E 8E C0   Mov es,ax      
Na základe zadeklarovania segmentov assembler sám správne priradí adresu a nie je treba použiť segment prefix napríklad es:es_var 
24 0010 A1 0000r   Mov ax,ds_var      
25 0013 26: 8B 1E 0000r   Mov bx,es_var      
26 0018 26: 8B 0E 0000r   Mov cx,es:es_var ;Ten istý seg ako predch.instr!!! 
27 001D 2E: 8B 16 0000r   Mov dx,cs_var ;Vdaka assume vie ze s CS 
28 0022 CB   ret      
29 0023 Nas_PROG ENDP      
30 0023 CSEG ENDS      
31 END Nas_prog      


 
2) Príklady skráteného zápisu segmentov v modeli small

Demo_B1 (Ta2-1.asm)

Príklad skrateného spôsobu definovania segmentov v Turboassemblerovom modeli small. (Nastavenie segmentu DS pomocou @data a nastavenie relatívnej adresy správy pomocou OFFSET Sprava). Procedúra zobrazí oznam ukončený $ a uložený v pamäti. pomocou Int 21/ ah=09H

Title (Ta2-1.asm) Demo INT 21H/ah=9 = vystup na display
 
  .MODEL small    
  .STACK  100h    
  .DATA      
    Sprava DB "Ahoj",13,10,"$"  
  .CODE      
  mov ax, @data ;Nastav DS
  mov ds, ax  
  mov  ah, 9 ;DOS vystup retazca s $
  mov  dx, OFFSET Sprava ;Nastavit relat adresu
  int  21h    
  mov  ah, 4ch  
  int  21h    
  END      

Demo_B2 (Ta2_1a.asm)

title (Ta2_1a.asm) Demo INT 21H/ah=40H
subttl Vystup na obrazovku, resp.tlaciaren pomocou INT21H/ah=40h
 
  .MODEL  small    
         
  .STACK  100h    
         
  .DATA      
    Sprava  DB "Ahoj",13,10,12
    Hallo_Lenght equ $-Sprava     ;$ zastupuje zaciat tab
         
  .CODE      
  mov  ax, @data    ;Nastav DS
  mov  ds, ax    
  mov  ah, 40h    ;DOS vystup retazca s $
  mov  bx, 1    ;pre Printer b=4
  mov  cx, Hallo_Length    ;Pocet znakov
  mov  dx, OFFSET Sprava    ;Nastavit relat adresu
  int  21h    
  mov  ah, 4ch    
  int  21h    
  END      

Demo_B3 (Ta2-1c.asm)

title (Ta2-1c.asm) Demo Úprava Ta2_1a.asm na tvar subor.com
 
   Model small  
.CODE      
  org  100h  
  mov ax, @data ;Nastav DS
  mov  ds, ax  
  mov ah, 9 ;DOS vystup retazca s $
  mov  dx, OFFSET Sprava ;Nastavit relat adresu
  int  21h  
  mov  ah,4ch  
  int  21h  
       
.DATA      
Sprava DB "Najprv tasm/l/n ta2-1c.asm, potom tlink ta2_1c.obj",13,10 
  db "Demonstracia pre exe2bin ta2-1c ta2_1c.com",13,10 
  db "Pretoze je DS bude si pytat jeho adr .Ahoj",13,10 
  db "Ak nema ine segmenty tak aj priamo tlink/t/x subor.obj" 
  db 13,10,"$"  
  END    

 

Demo_B4 (Ta2-3a.asm)

Procedúra zabezpečí zobrazenie výzvy na vloženie textu [výstup textu o dlžke v (cx) pomocou int21H/ah=40H (Handle=StdOut). Assembler používa automatické určenie dlžky reťazca Meldung pomocou $-Meldung a inštrukciu lea dx, Meldung / namiesto mov dx, offset Meldung ]. Po uložení vstupného textu z klávesnice (Handle=StdIn) o maximálnej dĺžke 80 znakov do pamäti (na adresu Vstup_Buffer pomocou int21H/ah=3FH) sa tento text zobrazí (pomocou int21H/ah=40H) na obrazovke (Handle=StdOut).

title (Ta2-3a.asm) Demo Handle (Kvôli zúženiu výpisu sú dlhé naveštia trocha upravené.)
Subttl Vstup retazca znakov/Vystup v opacnom poradi
 
  .MODEL  small    

.STACK  100h 

  .DATA      
MAXIMUM _STRING _LENGHT EQU 1000    
StringToReverse DB MAXIMUM _STRING _LENGHT  DUP (?)
ReverseString  DB MAXIMUM _STRING _LENGHT DUP (?)
  .CODE      
  mov  ax, @data Nastav DS
  mov  ds, ax  
  mov ah, 3fh  ;Dos vstup
  mov  bx, ;Std vstup StdIn
  mov  cx, MAXIMUM _STRING _LENGHT ;Pocet
  mov  dx, OFFSET StringTo Reverse ;Tu ulozit string
  int  21h    
  and  ax, ax ;Bol nejaky znak citany
  jz  Done   
  mov  cx, ax ;Dlzka retazca pocitadlo
  push  cx    
  mov  bx, OFFSET StringTo Reverse  
  mov  si, OFFSET Reverse String  
  add  si, cx  
  dec  si    
ReverseLoop:       
  mov  al, [bx] ;Nasled znak
  mov  [si], al ;Ulozit v opacnom porad
  inc  bx    
  dec  si    

loop Reverse _Loop 
  pop  cx    
  mov ah, 40h  ;DOS vystup retazca (cx)
  mov  bx, ;StdOut - consola-obrazovka
  mov  dx, OFFSET Reverse String  ;Nastavit relat adresu
  int 21h    
Done:        
  mov  ah, 4ch ;Dos
  int  21h    
  END      

 

Demo_B5 (Kurs1.asm)

Procedúra je obdobou Pgo1.asm a zabezpečí prečítanie reťazca znakov ( o dlžke deklarovanej v bunke MAXIMUM_STRING_LENGTH pre (cx), z adresy StringToReverse v pamäti pomocou int21H/ah=3FH ) a uloženie tohoto reťazca v opačnom poradí (na adresu ReverseString pomocou int21H/ah=40H).

title (Kurs1.asm) Demo HANDLE
Subttl Vstup retazca znakov a jeho vystup
 

.MODEL  Small


.STACK  100h 


.DATA


 Meldung  db  "Prvy   program, v TASM"  ,0dH,0aH 

db "Zadaj  text:",13,10 ;netreba $
DL_Meldung EQU  $-Meldung   ;finta automat dlzku
Vstup_Buffer  db 80 DUP(?) 
;nepotrebuje $
  .CODE      
STDIN  EQU 0    
STDOUT  EQU 1    
         
  mov  ax, @data ;Nastav DS
  mov  ds, ax  
         
  mov  bx, STDOUT  ;Vystup oznamu
  mov  cx, DL_Meldung  
  lea  dx, Meldung  ;=>mov dx,OFFSET Meldung
  mov  ah, 40h  ;Dos vystup retazca (cx)
  int  21H    
         
  mov  bx, STDIN  ;Standardny vstup
  mov  cx, 80H  ;Pocet
  lea  dx, Vstup_Buffer  ;Tu ulozit vst.znaky
  mov  ah, 3Fh  ;Dos vstup z KBD
  int  21H    ;Vystup AL=pocet vst.znakov
  JC  Done    ;Ak chyba tak CY=1
  mov  bx, STDOUT  ;Standard. zapis
  mov  cx, ax ;pocet zapis znak
  lea  dx, Vstup_Buffer  
  mov  ah, 40h ;DOS vystup na obrazovku
  int  21h    
Done:  mov ah, 4ch    ;Dos navrat
  int  21h    
  END      

Ta2-2.asm

Procedúra zobrazí oznam "Je po 12 hodine popoludni ?(y/n)$" a po stlačení klávesu Y/N vypíše buď "Dobre rano!",13,10,"$" alebo "Ahoj",13,10,"$", t.j. rôzne oznamy na konci s $,ktoré sú zobrazené pomocou Int21/ah=09H.
 
 
 title 
Turbo Assembler User's Guide priklad 2. 2
 subttl 
Skrateny sposob definovania segmentov
  .MODEL small
  .STACK 100h
  .DATA
 TimePrompt
DB "Je po 12 hodine popoludni ?(y/n)$"
 SpravaRanna 
Label Byte
  DB 13,10,"Dobre rano !",13,10,"$" 
 SpravaObed 
Label Byte
  DB 13,10, "Ahoj",13,10,"$"
  ;------------------------------------------------------------
  .CODE
  mov ax,@data                              ;Nastav DS
  mov ds,ax
  mov ah,9                                      ;DOS vystup retazca s $
  mov dx,OFFSET TimePrompt         ;Nastavit relat adresu
  int 21h
  mov ah,1                                      ;DOS Get znak
  int 21h
  cmp al,"y"                                     ;Ci Yes?
  jz JePoobede
  cmp al,"y"
  jnz JeRano
 JePoobede:
  mov dx,OFFSET SpravaObed
  jmp DisplayGreeting
 JeRano:
  mov dx,OFFSET SpravaRanna
 DisplayGreeting: 

  mov ah,9
  int 21h
  mov ah,4ch
  int 21h
  END

Ta2-4.asm

Procedúra zabezpečí vstup znaku z klávesnice (pomocou int 21h/ ah=1) a jeho echo na obrazovke (pomocou int21h/ ah=2).
 
 
 title 
Turbo Assembler User's Guide priklad str. 55
 subttl 
Vstup znaku a jeho echo na obrazovke
  .MODEL small
  .STACK 100h
  .DATA
  .CODE
 EchoLoop:
  mov ah,1                          ;DOS vstup znaku s klav
  int 21h
  cmp al,13                         ;Je to CR?
  jz EchoDone
  mov dl,al
  mov ah,2                         ;Vyst (DL) na obrazovke
  int 21h
  jmp EchoLoop
 EchoDone:
  mov ah,4ch                     ;Navrat do DOS
  int 21h
  END


 
 
3) Príklady objasňujúce atribúty EXTRN a PUBLIC

Demo_C1

Príklad hlavného programu a subrutiny , ktoré sa vďaka deklarácii code segmentov oboch procedúr ako PUBLIC uložia do spoločného Cseg. Bez použitia Public by sa uložili do separátnych Code segmentov (čo sa demonštruje na záver). Prenos parametrov do subrutiny sa uskutočňuje cez registre.
 
 
Prg (A16_4.asm) a sbr (A16_4s.asm) majú spoločný (public ) CSEG ‘code’.
Sbr SUBMUL sa volá z hlavneho programu= > je externá voči prg ale v sbr treba deklarovať, že je public, pretože je volaná z prg. Použité údaje QTY a PRICE sú deklarované v DSEG hlavného programu a vstupujú z hlavného prg.
Listing hlavného programuA16_4.ASM ;=>tlink/x a16_4.obj+a16_4s.obj

Prg A16_4.lst
 
1 EXTRN  SUBMUL:far  
2      
3 0000
sstack 
Segment para stack 'STACK'
4 0000 40*(????)   dw 64 dup(?)  
5 0080
Sstack 
ends  
6      
7 0000 Datasg segment para "DATA
8 0000 0140
QTY 
Dw 0140H ;mnozstvo
9 0002 2500
PRICE 
Dw 2500H ;cena
10 0004
Datasg 
ends ;prg QTY*PRICE
11      
12 0000
CSEG 
SEGMENT para PUBLIC "code"


;Public umožni spojit CSEG z hlavného prg a sbr. 
14 0000 
Start 
proc far  ;Hlavny program
15
assume cs:cseg, ds:datasg, ss:sstack
16 0000 1E    push ds   
17 0001 2B C0    sub ax,ax  
18 0003 50    push ax  
19 0004 B8 0000s    mov ax,datasg  
20 0007 8E D8    mov ds,ax  
21 0009 A1 0002r    mov AX,PRICE ;Cena
22 000C 8B 1E 0000r    mov BX,QTY  ;mnozstvo
23 0010 9A 00000000se    CALL SUBMUL  ;sbr
24 0015 CB    ret  
25 0016 
Start 
endp  
26 0016
Cseg 
ends  
27
END 
start  ;Navestie pre 1 instr hlav prg

Subroutina A16_4S.ASM
 
CSEG 
SEGMENT para PUBLIC "code"


;Public spoji cseg  - sbr a prg. 
3 0000
SUBMUL 
proc far  
4
Assume 
CS:CSEG  
PUBLIC 
SUBMUL ;!za assume ulozit public
6 0000 E8 0001    call C10MUL  ;sbr
7 0003 CB    Ret  
8 0004 
submul 
Endp  
       

     ;Multiply subroutine:
11 0004
C10MUL 
Proc ;Price in AX, qty in BX
12 0004 F7 E3    mul bx  ;Vysl v DX:AX
13 0006 C3    Ret  
14 0007 
C10MUL 
Endp  
15 0007 
cseg 
Ends  
16 
END 
   

 
 
  -----------------------debug spojeneho programu------------------
  u0 15
  1991:0000 1E                 PUSH DS 
  1991:0001 2BC0             SUB AX,AX 
  1991:0003 50                  PUSH AX 
  1991:0004 B89019          MOV AX,1990 
  1991:0007 8ED8             MOV DS,AX 
  1991:0009 A10200         MOV AX,[0002] 
  1991:000C 8B1E0000     MOV BX,[0000] 
  1991:0010 9A20009119  CALL 1991:0020 
  1991:0015 CB                RETF 
  -u20         prazdne 16-20h = spolocny cseg
  1991:0020 E80100         CALL 0024 
  1991:0023 CB                RETF 
  1991:0024 F7E3             MUL BX 
  1991:0026 C3                RET 

 
-r
AX=0000 BX=0000 CX=00B7 DX=0000 SP=0080 BP=0000 SI=0000 DI=0000 
DS=1978 ES=1978 SS=1988 CS=1991 IP=0000 NV UP EI PL NZ NA PO NC 
1991:0000 1E PUSH DS 
-g10 qty=(AX) price=(BX)= vynásobí ich
AX=2500 BX=0140 CX=00B7 DX=0000 SP=007C BP=0000 SI=0000 DI=0000 
DS=1990 ES=1978 SS=1988 CS=1991 IP=0010 NV UP EI PL ZR NA PE NC 
1991:0010 9A20009119 CALL 1991:0020 
-dds:0 f tu su data QTY=0140h a PRICE=2500h
1990:0000 40 01 00 25 00 00 00 00-00 00 00 00 00 00 00 00 @.%......
-p vysledok v DX:AX=2E4000
AX=4000 BX=0140 CX=00B7 DX=002E SP=007C BP=0000 SI=0000 DI=0000 
DS=1990 ES=1978 SS=1988 CS=1991 IP=0015 OV UP EI PL NZ NA PO CY 
1991:0015 CB RETF 
-p koniec
AX=4000 BX=0140 CX=00B7 DX=002E SP=0080 BP=0000 SI=0000 DI=0000 
DS=1990 ES=1978 SS=1988 CS=1978 IP=0000 OV UP EI PL NZ NA PO CY 
1978:0000 CD20 INT 20

 

u Verifikácia uloženia procedúr do segmentov

Bez deklarácie oboch segmentov ako public (v 12 riadku A16_4.asm a v 1 riadku A16_4s.asm) by sa po zlinkovaní takto modifikovaných hlavného programu A15_3.asm so subrutinou A15_3s.asm nevytvoril jeden spoločný Code segment, ale 2 nezávislé segmenty CSEG ako ilustruje vypis A16_3.map:
 
 
Start    Stop   Length   Name   Class
00000H    0003FH    00040H   SSTACK   STACK
00040H    00043H    00004H    DATA   DATA
=> 2segmenty CSEG ‘Code"!!! (align= para = 50H, 70H . Skuste tiež align=byte a porovnajte)
00050H    00067H    00018H    CSEG    CODE pre A16_3.asm
00070H    00076H    00007H    CSEG   CODE pre A16_3s.asm
=> Spoločný segment Program entry point at 0005:0000 

Demo_C2

Príklad hlavného programu a subrutiny, ktoré sa vďaka deklarácii code segmentov oboch procedúr ako PUBLIC uložia do spoločného Cseg. Prenos parametrov QTY a PRICE z Data segmentu do subrutiny sa uskutočňuje cez registre. Dáta QTY a PRICE sú deklarované v Data segmente hlavného programu sa do subrutiny sa prenášajú vďaka ich deklarovaniu v hlavnom programe ako PUBLIC a v subrutine ako EXTRN (QTY:word a PRICE:word ).

Prg a sbr majú spoločný (public ) CSEG ‘code’. Sbr SUBMUL sa volá z hlavneho programu => je externá voči prg ale v sbr treba deklarovať, že je public, pretože je volaná z prg. Použité údaje QTY a PRICE sú deklarované v DSEG hlavného programu a vstupujú zo sbr C10MUL a sú v hlavnom prg public a v sbr externé.
 
 
  Listing hlavného programu. A16_5.ASM
  1 EXTRN SUBMUL:far            ;=tlink/x a16_4.obj+a16_4s.obj
  2 PUBLIC QTY,PRICE             ;DATA sa pouziju az v sbr!!
  3 ;---------------------------------------------------------------
  4 0000    sstack segment para stack 'STACK'
  5 0000        40*(????) dw 64 dup(?)
  6 0080    sstack ends
  7 ;--------------------------------------------------------------
  8 0000   datasg segment para "DATA"
  9 0000   0140  QTY dw 0140H             ;mnozstvo
  10 0002 2500  PRICE dw 2500H         ;cena
  11 0004  datasg  ends                             ;prg QTY*PRICE
  12 ;---------------------------------------------------------------
  13 0000   CSEG SEGMENT para PUBLIC "code"
  ;Public umožni spojit CSEG sbr a hlav.prg
  15 0000   Start proc far                         ;Hlavny program
  16      assume cs:cseg,ds:datasg,ss:sstack
  17 0000 1E                       push ds
  18 0001 2B C0                 sub ax,ax
  19 0003 50                       push ax
  20 0004 B8 0000s             mov ax,datasg
  21 0007 8E D8 mov           ds,ax
  22 0009 9A 00000000se    CALL SUBMUL         ;DATA az v sbr
  23 000E CB                      ret
  24 000F                start      endp
  25 000F                            cseg ends
  26                          END    start                          ;Navestie pre 1 instr hlav prg!
  Subroutina A16_5S.ASM
  1     EXTRN QTY:WORD,PRICE:WORD        ;Boli def v hlav prg.!!!
  2 ;--------------------------------------------------------------
  3 0000   CSEG SEGMENT para PUBLIC "code"
  4 0000   SUBMUL proc far
  5   assume CS:CSEG
  6     PUBLIC SUBMUL                      ;!za assume ulozit public
  7 0000 E8 0001             call C10MUL                   ;sbr
  8 0003 CB                     ret
  9 0004               submul endp
  10 ;Multiply subroutine:
  12 0004                        C10MUL proc                  ;Nasobi DX:AX=(AX)*(BX)
  13 0004 A1 0000e         mov AX,PRICE                ;PRICE,QTY def v hl.prg!!
  14 0007 8B 1E 0000e    mov BX,QTY
                                      mul bx
  15 000B C3                   ret
  16 000C                        C10MUL endp
  17 000C                cseg ends
  18                                END 
  ------------------------------debug spojeneho prog --------------------------- 
  -u0 Debug hlavny program
  1D7D:0000 1E                  PUSH DS 
  1D7D:0001 2BC0              SUB AX,AX 
  1D7D:0003 50                   PUSH AX 
  1D7D:0004 B87C1D          MOV AX,1D7C 
  1D7D:0007 8ED8 MOV      DS,AX 
  1D7D:0009 9A10007D1D   CALL 1D7D:0010 
  1D7D:000E CB                  RETF 
  Výplň kvôli zaokruhleniu para =>Nasledujuci kód nie je ešte sbr !!
  1D7D:000F 00E8              ADD AL,CH - nie je prg. kod !! 
  -u10 Sbroutina spravne lebo para zaokruhlenie far
  1D7D:0010 E80100          CALL 0014 
  1D7D:0013 CB                 RETF 
   
  Druha sbr je near bez zaokruhlenia => hned nasleduje
  1D7D:0014 A10200          MOV AX,[0002] 
  1D7D:0017 8B1E0000      MOV BX,[0000] 
                                         mul bx
  1D7D:001B C3                 RET 
  -r
  AX=0000 BX=0000 CX=00AC DX=0000 SP=0080 BP=0000 SI=0000 DI=0000 
  DS=1D64 ES=1D64 SS=1D74 CS=1D7D IP=0000 NV UP EI PL NZ NA PO NC 
  1D7D:0000 1E PUSH DS 
  -g9
  AX=1D7C BX=0000 CX=00AC DX=0000 SP=007C BP=0000 SI=0000 DI=0000 
  DS=1D7C ES=1D64 SS=1D74 CS=1D7D IP=0009 NV UP EI PL ZR NA PE NC 
  1D7D:0009 9A10007D1D CALL 1D7D:0010         - far call
  -t
  AX=1D7C BX=0000 CX=00AC DX=0000 SP=0078 BP=0000 SI=0000 DI=0000 
  DS=1D7C ES=1D64 SS=1D74 CS=1D7D IP=0010 NV UP EI PL ZR NA PE NC 
  1D7D:0010 E80100 CALL 0014                           - near call 
  -t
  AX=1D7C BX=0000 CX=00AC DX=0000 SP=0076 BP=0000 SI=0000 DI=0000 
  DS=1D7C ES=1D64 SS=1D74 CS=1D7D IP=0014 NV UP EI PL ZR NA PE NC 
  1D7D:0014 A10200 MOV AX,[0002] DS:0002=2500- Price
  -t
  AX=2500 BX=0000 CX=00AC DX=0000 SP=0076 BP=0000 SI=0000 DI=0000
  DS=1D7C ES=1D64 SS=1D74 CS=1D7D IP=0017 NV UP EI PL ZR NA PE NC 
  1D7D:0017 8B1E0000 MOV BX,[0000] DS:0000=0140 - QTY
  -ge
  AX=2500 BX=0140 CX=00AC DX=0000 SP=007C BP=0000 SI=0000 DI=0000 
  DS=1D7C ES=1D64 SS=1D74 CS=1D7D IP=000E NV UP EI PL ZR NA PE NC 
  1D7D:000E CB        RETF 

Demo_C3 (Bfig_5-13 a Bfig_5-14)

Príklad hlavného programu pre výstup znaku obrazovku (Int 10H/ah=0EH). Znak sa v hlavnom programe uloží do bunky pamäte output_znak a volá sa extrn output_sbr:near (Bfig_5-14) Príklad je obdobou A16_5.asm. Odlišuje sa tým, že pamäťová bunka cez ktorú sa prenášajú znaky do subrutiny je deklarovaná ako PUBLIC v subrutine. Vďaka jej deklarácii ako EXTRN v hlavnom programe môže assembler korektne preložiť  kód programu.

Hlavný program (bfig513.lst) a sbr (bfig.514.lst) majú spoločný CodeSEG vďaka použitiu PUBLIC pri deklarovaní code segmentov sbr a prg. Pamäťová DS:bunka output_znak do ktorej sa ukladá bajt určený na zobrazenie je lokalizovaná v sbr spolu s procedúrou output_sbr pre výstup znaku. Preto sú output_znak a output_sbr z hľadiska hlavného programu externé a aby mohli byť využívané v hlavnom programe je treba ich v sbr zadeklarovať ako public. Pri zápise direktív si treba tiež povšimnúť spôsob špecifikovania typu dat (byte), resp. typ procedúry (near).
 
  Listing hlavného programu BFIG513.ASM
  1 0000 sstack segment stack
  2 0000 40*(????) dw 64 dup(?)
  3 0080 sstack ends
  4 ;--------------------------------------------------------------
   
  5 0000 Code SEGMENT public
  ;že ho možno kombinovat s inými segmentami rovnakého mena
   
  9 extrn output_sbr:near, output_znak:byte
  ;procedúra a premená sú definovane až v podprograme - sbr bfig514
   
  11       ASSUME CS:Code
  13 0000                 Start proc far
  14 0000 1E                    push ds                      ;Navratova adr int20h
  15 0001 B8 0000            mov ax,0                    ;pre segment
  16 0004 50                     push ax                      ;pre offset =0
  17 0005 FC                    cld                            ;clear Direction flag=>inc
  18 0006 8C C8               mov ax,cs                  ;Nastavenie DS =CS
  19 0008 8E D8               mov ds,ax
  21                        assume DS:code                  ;Nove priradenie
  23 000A BE 001Cr          mov si,offset message ;adr stringu message
  24 000D               slucka:
  25 000D AC                    lodsb                          ;Dalsi bajt spravy
  26 000E A2 0000e           mov output_znak,al    ;Ulozit do memory
  27 0011 E8 0000e           call output_sbr          ;Vystup znaku
  28 0014 80 3E 0000e 0A cmp output_znak,10   ;Ci je LF ?
  29 0019 75 F2                 jne slucka                    ;Naspat ak nie LF
  30 001B CB                     ret
  32 001C 54 6F 74 6F 20 6A 65 + message 
                                      db "Toto je test",13,10
  33 20 74 65 73 74 0D 0A
  35 002A                   start endp
  36 002A                   code ends
  37                            END start                           ;Navestie pre 1 instr!
  ===================================================
  Podprogram (sbr) Bfig514.asm pre výstup na obrazovku
  2 0000   Code SEGMENT public 
  ;že ho možno kombinovať s inými segmentmi rovnakého mena
   
  6   ASSUME CS:Code,ds:code                ;Toto musi byt splnene
  7 ;----------------------------------------
  8   public output_znak, output_sbr
  10 0000           ?? output_znak db ?                 ;Sem ulozi znak bfig513
  11 ;----------------------------------------
   
  12 0001   output_sbr proc near
  14 0001 A0 0000r mov al,output_znak         ;Dat znak na vystup
  15 0004 B4 0E      mov ah,14                      ;BIOS funkcia
  16 0006 BB 0000   mov bx,0                      ;aktivna vidostranka
  17 000C CD 10      int 10h                          ;Zobraz sbr
  18 000E C3           ret
  20 000F                output_sbr endp
  21 000F        code ends
  22                         END                               ;Bez mena!!!
  ------------------------------debug spojeneho prog ---------------------------
   Spojený hlavny program sbr bfig513.exe
   =>tlink/x bfig513+bfig514
  u0 1f 
  1990:0000 1E                  PUSH DS 
  1990:0001 B80000           MOV AX,0000 
  1990:0004 50                   PUSH AX 
  1990:0005                        FC CLD 
  1990:0006 8CC8               MOV AX,CS 
  1990:0008 8ED8               MOV DS,AX
  1990:000A BE1C00           MOV SI,001C 
  1990:000D AC                  LODSB 
  1990:000E A23000            MOV [0030],AL 
  1990:0011 E81D00            CALL 0031 
  1990:0014 803E30000A     CMP BYTE PTR [0030],0A 
  1990:0019 75F2                JNZ 000D 
  1990:001B CB                  RETF 
  -u31 Sbr bfig 514
  1990:0031 A03000            MOV AL,[0030] 
  1990:0034 B40E               MOV AH,0E 
  1990:0036 BB0000           MOV BX,0000 
  1990:0039 BA0000           MOV DX,0000
  1990:003C CD10              INT 10 
  1990:003E C3                  RET 
   
  -dcs:0 3e ulozenie prg hlavneho
  1990:0000 1E B8 00 00 50 FC 8C C8-8E D8 BE 1C 00 AC A2 30
  1990:0010 00 E8 1D 00 80 3E 30 00-0A 75 F2 CB 
   
  1990:001cOznam pre zobrazenie 54 6F 74 6F .h...0..urKToto
  1990:0020 20 6A 65 20 74 65 73 74-0D 0A je test..
   
  vypln 00 v dôsledku spojenia segmentov
  1990:002a 00 00 00 00 00 00 ......
  1990:0030 00 
   
  Sbr tu začina
  1990:0031 A0 30 00 B4 0E BB 00-00 BA 00 00 CD 10 C3 . 0.4.;..:..M.C
   
  -r zaciatok hlavného prg
  AX=0000 BX=0000 CX=00BF DX=0000 SP=0080 BP=0000 SI=0000 DI=0000 
  DS=1978 ES=1978 SS=1988 CS=1990 IP=0000 NV UP EI PL NZ NA PO NC 
  1990:0000 1E PUSH DS
   
  -g11 
  AX=1954 BX=0000 CX=00BF DX=0000 SP=007C BP=0000 SI=001D DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1990 IP=0011 NV UP EI PL NZ NA PO NC 
  1990:0011 E81D00 CALL 0031
   
  -t odskok do sbr
  AX=1954 BX=0000 CX=00BF DX=0000 SP=007A BP=0000 SI=001D DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1990 IP=0031 NV UP EI PL NZ NA PO NC 
  1990:0031 A03000 MOV AL,[0030] DS:0030=54
   
  -g3e
  AX=0E54 BX=0000 CX=00BF DX=0000 SP=007A BP=0000 SI=001D DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1990 IP=003E NV UP EI PL NZ NA PO NC 
  1990:003E C3 RET
   
  -t navrat zo sbr
  AX=0E54 BX=0000 CX=00BF DX=0000 SP=007C BP=0000 SI=001D DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1990 IP=0014 NV UP EI PL NZ NA PO NC 
  1990:0014 803E30000A CMP BYTE PTR [0030],0A DS:0030=54
   
  -t zistilo pri teste, ze znak nie je LF
  -g1b
  AX=0E0A BX=0000 CX=00BF DX=0000 SP=007C BP=0000 SI=002A DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1990 IP=001B NV UP EI PL ZR NA PE NC 
  1990:001B CB RETF
  -t
  AX=0E0A BX=0000 CX=00BF DX=0000 SP=0080 BP=0000 SI=002A DI=0000 
  DS=1990 ES=1978 SS=1988 CS=1978 IP=0000 NV UP EI PL ZR NA PE NC 
  1978:0000 CD20 INT 20

 

Bfig_9-3.asm

Test Keyboard Status - Meria čas stlačenia klávesu. Program registruje počet prechodov cez slučku "count" a ukladá výsledok ako DD (LSbajty počítadla ako DW v slove little a MSbajty počítadla ako DW slovo big), t.j. registruje čas (meraný trvaním prechodu cez sľučku "count") pokiaľ sa nestlačí nejaký kláves. Zo slučky výstup von až po stlačení medzery. Najprv sa testuje status klávesu. Jeho ASCII kód sa ukladá do AL. V prípade, že je AL=0, tak. atribut klavesu - Scancode sa uloží do AH.
 
 
  page ,132
 TITLE 
Keyboard Status - Meria cas stlacenia klavesu
   
 stackseg 
segment para stack
                db 64 dup("stack")
 stackseg 
ends
   
  ;-----------------------------------
 code 
segment
   assume 
cs:code,ss:stackseg
        little  dw 0                                  ;LSbajty pocitadla
          big 
dw 0                                  ;MSbajty pocitadla
  ;=============================================
  ;Program registruje pocet prechodov cez slucku "count" a uklada
  ;vysledok ako DD v big:little,t.j. registruje cas pokial sa ne-
  ;stlaci nejaky klaves. Zo slucky von az pri stlaceni medzery.
  ;Najprv status klavesy. ASCII =kod klavesu uklada do AL. Scancode 
  ;t.j. atribut klavesu do AH ak je AL=0 a nie je ASCII.
  ;==============================================
   
 count 
proc far
   
  push ds                                      ;Uschova navrat do DOS
  mov ax,0 
  push ax
   
 add_one:
  inc little
  jnz still_low
  inc big                                        ;ked do hornej casti cisla
   
 still_low:
  mov ah,1                                   ;Zistenie statusu klavesnice
  int 16h                                      ;Ak stlacena tak ZF=ZR=1
  jz add_one                                ;AK nebola stlacena tak naspat
   
  mov ah,0
  int 16h                                     ;Cita znak do AL,atrib do AH
  cmp al," "                                 ;Ci je medzera ?
  jnz add_one
  ret
   
 count 
endp
 code 
ends
 end 
count


 
µ Koncepcia prenosu dát do podprogramov

Prenos parametrov z hlavného programu do podprogramu, resp. naopak sa môže vykonať buď prostredníctvom:

  • univerzálnych registrov (napríklad cez AX a BX v A_16_4.asm);
  • cez pamäťové bunky (napríklad bajt Output_znak v bfig513a asm + bfig514a.asm, poprípade slová QTY a PRICE v A_16.5.asm );
  • zásobníka (Stack). Pritom cez zásobník možno preniesť do subrutiny buď:
    • nepriamou metódou adresu parametra (anglicky call by address). Tento spôsob prenosu parametrov do podprogramu je bežný pri volaní assemblerovských podprogramov z programov napísaných v programovacích jazykoch vyššej úrovne, napríklad z jazyka QBasic.
    • priamou metódou priamo hodnotu parametra (anglicky call by value - ilustruje nasledujúci program). Z hľadiska prenosu parametra cez zásobník sú oba spôsoby rovnaké .

Nasledujúci príklad demonštruje spôsob prenosu parametra priamou metódou, ktorý pozostáva najprv v uložení parametrov do zásobníka a v ich následnom vybratí na začiatku subrutiny. Pritom prvý parameter uložený do zásobníka bude v ňom najhlbšie. Okrem parametrov sa pri odskoku na obslužný program ukladá do zásobníka aj návratová adresa. Táto adresa môže byť rôzne dlhá. V prípade Near:Call sa ukladá len IP a adresa bude len 2 bajtová = SP:=SP-2 , v prípade Far:Call treba uložiť CS:IP a preto bude posuv SP:=SP-4. Celá táto manipulácia je korektná vtedy, ak po vykonaní subrutiny zostane správne nastavený ukazovateľ zásobníka SP. Preto sa pri manipulácii s údajmi cez zásobník nepoužíva priamo ukazovateľ zásobníka SP, ale pomocný ukazovateľ BP, ktorého obsah je na začiatku zosúhlasený s SP. Ďalej je dôležité použitie rovnakého početu inštrukcii PUSH/POP v subrutine alebo aspoň ich správny počet vykompenzovať v návratovej inštrukcii RETn, kde n = 2*p reprezentuje chýbajúci počet inštrukcii POP, v súvislosti s predošlým uložením p parametrov. Postup pri ukladaní parametrov do zásobníka a ich získanie zo zásobníka v subrutine je nasledovný:
 
 
 our_prog  proc far ;= časť z hlavného programu
  push ax                   ;1 parameter v AX ; SP<- SP-2
  push bx                   ;2 parameter v BX ; SP<- SP-2
  push cx                   ;3 parameter v CX ; SP<- SP-2
  push dx                   ;4 parameter v DX ; SP<- SP-2
  call subroutine     ;Prenos riadenia do subrutiny ; SP<- SP-2, resp.4
  ;=> ďalšie pokračovanie programu, obnova SP.
  Our_prog endp        ; koniec nášho hlavného demoprogramu
  ;---------------------------------------------------------------------------------
  Subroutine proc near ;= bude uložené len IP

push bp                    ;úschova BP
  mov bp,sp                ;Zosuhlasenie SP s BP
  mov ax,[bp+2]          ;4 parameter pôvodne z [DX]
  mov bx,[bp+4]          ;3. parameter pôvodne z [CX]
  mov cx,[bp+6]          ;2. parameter pôvodne z [BX]
  mov dx,[bp+8]         ;1. parameter pôvodne z [AX]
  pop bp
  ret n                       ; n = 2* počet parametrov
 Subroutine  endp
  ;---------------------------------------------------------------------------------

u Demonštácia uvedných faktov:
 
 
 TITLE 
A_16.6.asm Príklad hlavného programu, ktorý volá SubMul
 subttl 
keď parametre sa prenášajú do SubMul cez zásobník !
  page 60 , 132
 EXTRN 
SUBMUL:far                                                     ;=tlink/x a16_4.obj+a16_4s.obj
  ;---------------------------------------------------------------
 sstack 
segment para stack 'STACK'
            dw 64 dup(?)
 sstack 
ends
  ;--------------------------------------------------------------
  datasg 
segment para "DATA"
 QTY 
dw 0140H                                                          ;1. parameter = množstvo
 PRICE 
dw 2500H                                                          ;2. parameter = cena
 datasg 
ends 
  ; ---------------------------------------------------------------
 CSEG 
SEGMENT para PUBLIC "code" 
 Start 
proc far                                                              ;Hlavny program
assume 
 cs:cseg,ds:datasg,ss:sstack
  push ds                                                               ;1 DW do stacku
  sub ax,ax
  push ax                                                               ;2 DW
  mov ax,datasg
  mov ds,ax
  PUSH PRICE                                                      ;3 DW
  PUSH QTY                                                         ;4 DW
  CALL SUBMUL                                                   ;5,6 DW =Far:Call 
  ret                                                                      ;-SP<= SP+4
 start 
endp
 cseg 
ends
 END 
 start 
                                                     ;Navestie pre 1 instr hlav prg! 
  ;--------------------------------------------------------------------------------
  Výpis subrutiny A16_6S.ASM ktorá vynásobí QTY*PRICE;
  2 0000  CSEG SEGMENT para PUBLIC "code"
  3 0000  SUBMUL proc far 
  4                        assume CS:CSEG
  5                         PUBLIC SUBMUL       ;!za assume uložiť public
  6 0000 55            PUSH BP                  ;6+1 DW =BP na-2*7=> 0Eh
  7 0001 8B EC      MOV bp,sp
  8 0003 8B 46 08  MOV AX,[BP+8]         ;QTY je =na SP+6
  9 0006 8B 5E 06  MOV BX,[BP+6]        ;PRICE je =>na SP+8
  10 0009 F7 E3     mul bx
  11 000B 5D          pop bp
  12 000C CA 0004 ret 4                         ;kompenzuje pop
  13 000F   submul endp
  14 000F      cseg ends
  15 END
  ;---------------------------------------------------------------------------------------
  -rzaciatok hlavnej procedury
  AX=0000 BX=0000 CX=00BF DX=0000 SP=0080 BP=0000 SI=0000 DI=0000 
  DS=1B76 ES=1B76 SS=1B86CS=1B8F IP=0000 NV UP EI PL NZ NA PO NC 
  1B8F:0000 1E PUSH DS
  -g11
  AX=1B8E BX=0000 CX=00BF DX=0000 SP=0078 BP=0000 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0011 NV UP EI PL ZR NA PE NC 
  1B8F:0011 9A20008F1B CALL 1B8F:0020 
  Vstup do SBR
  AX=1B8E BX=0000 CX=00BF DX=0000 SP=0074BP=0000 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0020 NV UP EI PL ZR NA PE NC 
  1B8F:0020 55 PUSH BP 
  AX=1B8E BX=0000 CX=00BF DX=0000 SP=0072 BP=0000 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0021 NV UP EI PL ZR NA PE NC
  1B8F:0021 8BEC MOV BP,SP 
  AX=1B8E BX=0000 CX=00BF DX=0000 SP=0072 BP=0072 SI=0000 DI=0000
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0023 NV UP EI PL ZR NA PE NC 
  1B8F:0023 8B4608 MOV AX,[BP+08] SS:007A=2500=PRICE
  AX=2500 BX=0000 CX=00BF DX=0000 SP=0072 BP=0072 SI=0000 DI=0000
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0026 NV UP EI PL ZR NA PE NC
  1B8F:0026 8B5E06 MOV BX,[BP+06] SS:0078=0140=QTY
  AX=2500 BX=0140 CX=00BF DX=0000 SP=0072 BP=0072 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0029 NV UP EI PL ZR NA PE NC 
  1B8F:0029 F7E3 MUL BX 
  AX=4000 BX=0140 CX=00BF DX=002E SP=0072 BP=0072 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=002B OV UP EI PL NZ NA PO CY 
  1B8F:002B 5D POP BP 
  AX=4000 BX=0140 CX=00BF DX=002E SP=0074 BP=0000 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=002C OV UP EI PL NZ NA PO CY 
  1B8F:002C CA0400 RETF 0004 =vykomenzovat zásobník 
  AX=4000 BX=0140 CX=00BF DX=002E SP=007C BP=0000 SI=0000 DI=0000 
  DS=1B8E ES=1B76 SS=1B86 CS=1B8F IP=0016 OV UP EI PL NZ NA PO CY 
  1B8F:0016 CB RETF = > po vykonaní retf bude SP = 0080 ako na začiatku. 


 
µ
Makroinštrukcie

Makroinštrukcia je pokyn pre prekladač, aby do cieľového programu zaradil vopred definovanú postupnosť inštrukcii, tzv. rozvoj makroinštrukcie, čo je vlastne otvorený podprogram. Makroinštrukcie alebo žargónovo makrá sú definované menom + vlastným obsahom (telom makra) a nakonci s ENDM. Assembler nahradí makro v mieste výskytu makra blokom kódov (nazýva sa tiež rozvojom makra alebo subsitúciou makra). Pri listingu sa objaví +, (resp. 1) pri dosadených kódoch.

Pseudoinštrukcia (direktíva) je príkaz symbolického programovacieho jazyka, ktorý sa neprekladá do cieľového programu, ale ovplyvňuje prekladač.
 

 Syntax makra:
 
  name MACRO [parameter[,parameter]...]  
   ..... telo makra
  ENDM  

 
 
1.
Jednoduché makro => bez parametrov

Makrá bez parametrov - sa používajú veľmi často pod názvom symbolické konštanty, pretože zbavujú program najrôznejšich "magických čísel" ktoré sa bez vysvetlenia objavujú v programe.

A15_1.asm: Príklad použitia jednoduchého makra - bez parametrov.
 
 
  A15_1.asm
 TITLE 
A15_1 Priklad na Macro
  page 60 , 132
  ;--------------------------------------------------------------
 INIT1 
MACRO                                               ;def macra
 ASSUME 
cs:CSEG,DS:DATA,SS:SSTACK,ES:DATA
  push ds
  sub ax,ax
  push ax
  mov ax,data
  mov ds,ax
  mov es,ax
  ENDM                                                ;end macra
  ;---------------------------------------------------------------
 Sstack 
segment para stack 'STACK'
  dw 32 dup(?)
 Sstack 
ends
  ;--------------------------------------------------------------
 Data 
segment para "DATA"
 MESSGE 
db "Test makroinstrukcie","$"
 DATA 
ends
  ;---------------------------------------------------------------
   
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  INIT1                                        ;MACRO
  lea dx,messge                                              ;adresa stringu message
  mov ah,09                                                   ;zobrazenie
  int 21h
  Ret
 Start 
endp
  Cseg 
ends
 END 
start                                                    ;Navestie pre 1 instr! 
  ----------------------------------------------------------------------------
   
  Listning A15_1.lst - časti vloženého macra do procedúry
  (rozvinutú časť makra pri listingu označilo 1)
  22 0000                    CSEG SEGMENT para "code"
  23 0000                    Start proc far
  24 INIT1                                                      ;MACRO
  1 25 0000 1E             push ds
  1 26 0001 2B C0        sub ax,ax
  1 27 0003 50              push ax
  1 28 0004 B8 0000s   mov ax,data
  1 29 0007 8E D8        mov ds,ax
  1 30 0009 8E C0        mov es,ax
  31 000B 8D 16 0000r  lea dx,messge           ;adresa message
  32 000F B4 09            mov ah,09                 ;zobrazenie
  33 0011 CD 21            int 21h
  34 0013 CB                ret
  35 0014                     start endp
  36 0014                     cseg ends
  37                              END start            ;Navestie pre 1 instr!

 
2
Makro s parametrami 

Makrá s parametrami - sa používajú ako náhrada často používaných krátkych funkcii alebo dlhých, opakujúcich sa komplikovaných výrazov, pre zlepšenú čitateľnosť programu.

Mená parametrov (CSNAME,DSNAME, SSNAME su tzv. dummy arguments = fiktívne, prázdne, zdanlivé, nastrčené panáky => za ne sa dosadia skutočné mená !!

 

A15_2.asm: Príklad použitia jednoduchého‚ makra - s parametrami.
 
 
  Príklad: definovanie makra s fiktívnymi parametrami
   
 INIT2 
MACRO csname, dsname, ssname                           ;def macra
 ASSUME  cs:CSname,DS:DSname,SS:SSname,ES:DSname
  push ds
  sub ax,ax
  push ax
  mov ax,dsname
  mov ds,ax
  mov es,ax
  ENDM
   
  a jeho použitie v procedúre (napr . A15_2.asm)
   
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  INIT2 cseg,data,sstack               ;MACRO
  lea dx,messge                          ;adresa stringu message
  mov ah,09                                ;zobrazenie
  int 21h
  ret
 Start 
endp
 Cseg 
ends

 
3. 
 Vnorené makro
 
  Príklad makra MS_DOS , ktoré je vnorené do makra Write
  DOS equ 21H
 a./  Write MACRO Adresa, PocetB
  LEA DX,Adresa 
  MOV CX,PocetB 
  MS_DOS                                           ;= >volá macro b./ 

ENDM
b./  MS_DOS MACRO Number
   MOV AH,Number
  INT 21H
  ENDM


 
µ
Špecialne makrooperátory
 
F ; - oddeľuje text komentára od vlastného makra. V mode .XALL sa ; nezobrazuje. V mode .LALL sa vypiše aj komentár.
F ;;  - generuje kód ; a ani v .LALL sa nezobrazí.

Assembler môže byť nastavený do módu :
 
 
F .XALL - implicitne = >zobrazí sa len výpis inštrukcii, ktoré generuje objektívny kód.
.LALL  - (List All) = vypíše aj komentár s ; ale potlačí ;;
F .SALL - (Suppress all) = potlačí rozvoj výpisu makra.

A15_3.asm: Príklad na použitie .LALL , .SALL a .XALL na potlačenie rozvinutia makra.
 
 
  Priklad na potlačenie rozvinutia makra.
  A15_3.asm - pouzitie .LALL a .SALL
 INIT2 
MACRO csname,dsname,ssname                    ;def macra
  ASSUME cs:CSname,DS:DSname,SS:SSname,ES:DSname
  push ds
  sub ax,ax
  push ax
  mov ax,dsname
  mov ds,ax
  mov es,ax
  ENDM                                                                     ;end macra
  ;---------------------------------------------------------------
 PROMPT 
MACRO MESSGE
  lea dx,messge
  mov ah,09
  int 21h
  ENDM
  ;-----------------------------------------------------------------
 Sstack 
segment para stack 'STACK'
  dw 32 dup(?)
 Sstack 
ends
  ;--------------------------------------------------------------
 Data 
segment para "DATA"
MESSG1 
db "Meno zakaznika?",13,10,"$"
Messg2 
db "Adresa zakaznika?","$"
 DATA 
ends
  ;---------------------------------------------------------------
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  .SALL                                          ;Potlačí rozvoj výpisu nasledujúcich makier
  INIT2 cseg,data,sstack
  PROMPT MESSG1
  .LALL                                           ; rozvinie ďalšie makrá
  prompt messg2
  ret
 Start 
endp
 Cseg 
ends
 END 
start                                      ;Naveštie pre 1 instr! 
  --------------------------------------------------------------------------------
  Listing časti procedúury A15_3.asm s potlačeným a rozvinutým macrom.
  Makro INTľ2 a Prompt messg1 majú potlačený výpis, kdežto makro Prompt messg2 sa vypíše pri listingu.
  32 0000                Start proc      far
  33               INIT2 cseg,data,sstack                  ; MACRO
  34               PROMPT MESSG1
  35               prompt messg2
  1 36 0013 8D 16 0012r   lea dx,messg2
  1 37 0017 B4 09            mov ah,09
  1 38 0019 CD 21            int 21h
  39 001B CB                   ret
  40 001C                 start endp

 
µ
Lokálne náveštia

Aby sa pri viacnásobnom výskyte makra nehlásila chyba v dôsledku nejednoznačnosti polohy náveštia treba deklarovať náveštia v makre ako lokálne (hneď za menom makra a fiktívnymi menami parametrov). Pri listingu sa viacnásobne použité lokálne naveštia nezobrazia menom ale ??0000, ???0001 a pod.

A15_4.asm: Príklad použitia lokálnych náveštíí LOCAL (=??0000, ??00001 atd)
 
 
  Príklad použitia lokálnych náveštíi v makre. - A15_4.asm. 
   
 INIT2a 
MACRO csname,dsname,ssname                 ;def macra
          ASSUME cs:CSname,DS:DSname,SS:SSname
  push ds
  sub ax,ax
  push ax
  mov ax,dsname
  mov ds,ax
  ENDM                                                      ;end macra
  ;---------------------------------------------------------------
   
 DIVIDE 
MACRO dividend,divisor,quotient
                                   ;AX=div'd, BX=divisor, CX=quotient 
                                   ;Delenie postupnym odcitavanim .                                ; Zvysok v AX
  LOCAL COMP
  LOCAL OUT
  mov ax,dividend           ;nastav delenca dividend
  mov bx,divisor              ;nastavenie delitela divisor
  sub cx,cx                     ;clear quotient
 COMP:  cmp ax,bx                  ;div´d<div´r?
  jb out                          ;ano exit
  sub ax,bx                    ;div'd-div'r
  inc cx                          ;+1 do quotient
  jmp comp
 OUT:  mov quotient,cx         ;uloz quotient
  ENDM
  ;-----------------------------------------------------------------
 sstack 
segment para stack 'STACK'
               dw 32 dup(?)
 sstack 
ends
  ;--------------------------------------------------------------
 data 
    segment para "DATA"
 DIVDND 
    dw 150                              ;delenec
 DIVSOR 
    dw 27                                ;delitel
 QUOTNT 
    dw ?                                  ;vysledok
 DATA 
    ends
  ;---------------------------------------------------------------
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  .SALL                               ;POTLACI ROZVOJ
  INIT2a cseg,data,sstack     ;MACRO
  .LALL                       ;rozvinie all
  DIVIDE DIVDND,DIVSOR,QUOTNT
  ret
 start 
endp
 cseg 
ends
 END 
start                          ;Navestie pre 1 instr! 
  -----------------------------------------------------------------------------
   
  Listing časti výpisu makier A15_4.lst s lokálnymi náveštiami
   
  30 0000                Data segment para "DATA"
  31 0000 0096        DIVDND        dw      150       ;delenec
  32 0002 001B        DIVSOR       dw       27        ;delitel
  33 0004 ????        QUOTNT      dw       ?          ;zvyšok
  34 0006 DATA       ends
  35 ;---------------------------------------------------------------
  36 0000                 CSEG SEGMENT para "code"
  37 0000                 Start proc far
  38                                      INIT2a cseg,data,sstack
  39                                      DIVIDE DIVDND,DIVSOR,QUOTNT
  1 40                                     ; AX=div'd, BX=divisor, CX=quotient
  1 41 0009 A1 0000r                     mov ax, DIVDND
  1 42 000C 8B 1E 0002r                mov bx, DIVSOR 
  1 43 0010 2B C9                          sub cx, cx 
  1 44 0012 3B C3             ??0000: cmp ax, bx
  1 45 0014 72 05                            jb ??0001
  1 46 0016 2B C3                           sub ax, bx 
  1 47 0018 41                                 inc cx 
  1 48 0019 EB F7                           jmp ??0000
  1 49 001B 89 0E 0004r    ??0001: mov QUOTNT, cx 
  50 001F CB                        ret
  51 0020                             start endp
  52 0020                             cseg ends
  53 END                              start

 
µ Zahrnutie makra do knižnice makier - MACRO.LIB

Pomocou textového editora uložiť makrá do súboru MACRO.LIB.  V prípade potreby ich možno vyvolať pomocou operátora INCLUDE, ktorý sa musí byť pred výskytom makra.
 
 
  Napr.: INCLUDE B:\ Macro.lib

Ak sa nezadá prípona .LIB assembler implicitne dosadí .lib. V listingu sa pri dosadenom kóde makra dosadí C (copy) v 3 stĺpci.

 
µ
Odstránenie makier z výpisu

F IF1 - Assembler je 2 priechodový prekladač, takže jeho kód z 1 priechodu možno použiť a výpis do listingu potlačiť pomocou IF1. Napríklad:
 
 
  IF1  
    INCLUDE B:\macro.lib
  ENDIF  

po preložení a výpise sa zobrazí len ENDIF
 
F PURGE  - odstránenie neželaných makier z výpisu. 
 
Napr.:      
    IF1  
      INCLUDE B:\macro.lib
    ENDIF  
  PURGE prompt, divide     

Pôsobením príkazu sa vymaže z výpisu nepotrebné makrá prompt, divide.
 
 
F REPT (Repetition) - opakovanie bloku príkazov zakončeného ENDM.
 
  Syntax: REPT expression
 
Napr.: N=0
  Rept 5        ;=> zopakuje 5*0
  N=N+1
  DB N          ;=> DB=1 až DB=5
  ENDM
 
 
F IRP (Indefinite Repetition) 
 
  Syntax:  IRP dummy,<arguments>
 
Napr.: IRP N,<3,9,14,25,28 > => generuje DB=3, DB=9, .. DB=28
  DB N  
  ENDM  
 
 
F IRPC (Indefinite Repeat Character) 
 
  Syntax:  IRPC dummy,string

Napr.: IRP N,345678  =generuje DW=3, DWB=4 ..ako retazce
  DW N  
  ENDM  
 
 
F IFxx  - Podmienené pseudooperátory.
 
Napr.: IFxx Podmienka    napr. IFNDEF symbol EXTRN
  [ELSE]     voliteľné [resp. EXITM= výstup]
  ENDIF     musi byť na záver

A15_5.asm

Príklad použitia operátora INCLUDE, ktorý umožňuje vyvolať makra z knižnice makier a tiež demonštrácia IF1 na odstránenie výpisu makier, ktoré už boli použité pri 1 priechode prekladača.

  Priklad A15_5.asm
  na použitie makier z knižnice s potlačením výpisu makier pomocou IF1. 
 TITLE 
A_15.5.asm Priklad na puzitie Library include
 subttl 
pouzitie INCLUDE orginal s IF1
  ;--------------------------------------------------------------
  IF1
  INCLUDE c:\jazyky\asm\asmexp\abel\macro.lib
  ENDIF
  ;-----------------------------------------------------------------
 sstack 
segment para stack 'STACK'
  dw     32          dup(?)
 sstack 
ends
 data 
segment para "DATA"
 MESSGE 
db "Test of macro","$"
 DATA 
ends
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  INIT cseg,data,sstack                               ;Obe makra sú z macro.lib
  PROMPT messge
  ret
 start 
endp
 cseg 
ends
 END 
start                                                        ;Navestie pre 1 instr! 

Listing programu A15-5A.ASM - klasicky a v skrátenom tvare

u Bez použitia IF1 by bol nasledujúci listing programu:

  1. zopakovalo by výpis makier na začiatku programu a potom
  2. tiež by ich rozvinulo na mieste ich aplikácie.( časť výpisu označená na boku 1)
u Vďaka aplikácii IF1 sa potlačí výpis na začiatku programu medzi označením ==.
 
 
1 ;--------------------------------------------------------------
=== Začiatok časti výpisu, ktorá sa vypustí vďaka pôsobeniu IF1 ====
2 INCLUDE c:\jazyky\asm\asmexp\abel\macro.lib
1 3                                                                 ;---výpis makra 1------------------
1 4     INIT MACRO csname,dsname,ssname
1 5     ASSUMEcs:CSname,DS:DSname,SS:SSname,ES:Dsname
1 6     push ds
1 7     sub ax, ax
1 8     push ax
1 9     mov ax, dsname
1 10   mov ds, ax
1 11   mov es, ax
1 12   ENDM                                                     ;end macra
1 13                                                                  ;----výpis makra2----------------
1 14   PROMPT MACRO MESSGE
1 15   lea dx, messge
1 16   mov ah, 09
1 17   int 21h
1 18   ENDM
1 19 == Koniec časti výpisu, ktorá sa vypustí vďaka pôsobeniu IF1 ===
 
20 ;-----------------------------------------------------------------
21 0000        sstack segment para stack 'STACK'
22 0000        20*(????)      dw     32     dup(?)
23 0040        sstack ends
24 ;--------------------------------------------------------------
 
25 0000        data segment para "DATA"
26 0000 54 65 73 74 20 6F 66 + MESSGE db "Test of macro","$"
27 20 6D 61 63 72 6F 24
28 000E        DATA ends
29 ;---------------------------------------------------------------
 
30 0000       CSEG SEGMENT para "code"
31 0000             Start proc far
32             INIT cseg,data,sstack               ;MACRO
1 33 0000 1E               push ds
1 34 0001 2B C0          sub ax,ax
1 35 0003 50                push ax
1 36 0004 B8 0000s      mov ax,data
1 37 0007 8E D8           mov ds,ax
1 38 0009 8E C0           mov es,ax
39                                PROMPT messge
1 40 000B 8D 16 0000r lea dx,messge
1 41 000F B4 09           mov ah,09
1 42 0011 CD 21           int 21h
43 0013 CB                   ret
44 0014           start endp
45 0014           cseg ends
46                   END start                                                       ;Navestie pre 1 instr!

 
 u Úprava programu A_15.5b.asm
  s použitím IF1 a .SALL na potlačenie výpisu makier.
   
  ;--------------------------------------------------------------
  IF1
  INCLUDE c:\jazyky\asm\asmexp\abel\macro.lib
  ENDIF
  ;-----------------------------------------------------------------
 sstack 
segment para stack 'STACK'
  dw           32     dup(?)
 sstack 
ends
  ;--------------------------------------------------------------
 data 
segment para "DATA"
 MESSGE  db         "Test of macro","$"
 DATA 
ends
  ;---------------------------------------------------------------
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  .sall
  INIT cseg,data,sstack                               ;MACRO
  PROMPT messge
  ret
  start endp
  cseg ends
 END 
start                                                            ;Navestie pre 1 instr! 
  ---------------------------------------------------------------------------------
   
  Listing A15_5B.ASM - výsledok použitia INCLUDE a IF1+.SALL
  1 ;--------------------------------------------------------------
  Toto sa potlačilo pri výpise
  2 ;-----------------------------------------------------------------
  3 0000    sstack segment para stack 'STACK'
  4 0000              20*(????)      dw     32    dup(?)
  5 0040    sstack ends
  6 ;--------------------------------------------------------------
  7 0000    data segment para "DATA"
  8 0000             54 65 73 74 20 6F 66 + MESSGE db "Test of macro","$"
  9                     20 6D 61 63 72 6F 24
  10 000E  DATA ends
  11 ;---------------------------------------------------------------
  12 0000   CSEG SEGMENT para "code"
  13 0000   Start proc far
  14                   INIT cseg,data,sstack
  15                   PROMPT messge
  16 0013 CB     ret
  17 0014    start   endp
  18 0014    cseg ends
  19 END    start


 
 
µ
Príklad knižnice - Macro.lib

je to textový súbor s koncovkou .lib, v ktorom sú makrá. Zo súboru sa natiahnu  pri kompilácii programu pomocou INCLUDE potrebné makra.

   
  ;;--------------------------------------------------------------
  INIT MACRO csname,dsname,ssname      ;def macra
      ASSUME cs:CSname,DS:DSname,SS:SSname,ES:DSname
  push ds
  sub ax, ax
  push ax
  mov ax, dsname
  mov ds, ax
  mov es, ax
  ENDM                                                      ;end macra
  ;;---------------------------------------------------------------
   
  LOCATE MACRO row,col
  ;;Presunie kurzor na zadany row a col
  push dx
  mov dh,row
  mov dl,col
  MOVE_CURSOR
  pop dx
  ENDM
  ;;---------------------------------------------------------------
   
  MOVE_CURSOR MACRO
  LOCAL OK,VS ;navestia len pre tuto sbr
  ;;Presunie kurzor na riadok=(DH) a stlpec=(DL). AK cislo riadku 
  ;;je 24 alebo cislo stlpca 79 tak budu 0.
  push ax
  push bx
  cmp dh,24
  jna OK
  sub dh,dh
 OK: cmp dl,79
  jna VS
  sub dl,dl
 VS:  VIDEO_STATE                              ;zisti akt videopage
  mov ah, 2
  int 10h
  pop bx
  pop ax
  ENDM
  ;;---------------------------------------------------------------
   
  PROMPT MACRO messge 
  ;;zobrazi riadok zakonceny $ na adrese messge
  Push dx
  Lea dx,DS:messge
  PROMPT_DX
  Pop dx
  ENDM
  ;;----------------------------------------------------------------
   
  PROMPT_DX MACRO
  ;;zobrazi riadok zakonceny $ ,ktoreho offset je v DX 
  Push ax
  Mov ah,09
  Int 21h
  Pop ax
  ENDM
  ;;-----------------------------------------------------------------
   
  POP_REG MACRO reg_list
  ;;Uschova registrov - pozor zoznam v opacnom poradi ako pri PUSH
  IRP reg,<reg_list>                            ; Indefinite repeat
  pop reg
  ENDM
  ENDM
  ;;----------------------------------------------------------------
   
  PUSH_REG MACRO reg_list
  ;;Uschova registrov
  IRP reg,<reg_list>                            ; Indefinite repeat
  push reg
  ENDM
  ENDM
  ;;----------------------------------------------------------------
   
  ROLL MACRO xroll,hrow,hcol,drow,dcol,atrib
  PUSH_REG <AX,BX,CX,DX>
  mov al, xroll
  mov ch, hrow 
  mov cl, hcol
  mov dh, drow
  mov dl, dcol
  mov bh, atrib
  mov ah, 06
  int 10h
  POP_REG <DX,CX,BX,AX>             ;POZOR opacne ako pri push
  ENDM
  ;;-----------------------------------------------------------------
   
  VIDEO_STATE MACRO
  ;;Zisti aktual mod=(AL) a akrual videopage =(BH)
  mov ah, 15
  int 10h
  ENDM
  ;;--------------------------------------------------------------
   
  VYPLN MACRO vzor
  LOCAL VYP1
  ;;Vyplni obrazovku znakom ,vymazž ju
  push dx
  push cx
  mov dl,vzor
  mov cx, 960*2                                    ; 24riadkov*80
  mov ah, 2
 VYP1:  int 21h
  loop VYP1
  pop cx
  pop dx
  ENDM

Rozh1m.asm

Príklad rozhodovacieho programu s makrami volanými pomocou include. Program po zadaní voľby v tvare čísla vyplní obrazovku rôznym podkladovým vzorom.
 
 
  IF1
  INCLUDE c:\jazyky\asm\asmexp\abel\macro.lib
  ENDIF
 .model 
small
 .stack 
100h
 .data

 vyber 
dw prog1,prog2,prog3,koniec       ;voľba programu
 sprava 
db 7  dup(0b0h), 0dah, 34 dup(0c4h), 0bfh,13,10
  db 7  dup(0b0h),0b3h," ponuka dna: ",13 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0b3h," 1 srdiecka ",3 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0b3h," 2 noticky ",3 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0b3h," 3 snezenie ",3 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0b3h," 4 koniec ",3 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0b3h," V y b e r si !!",5 dup(20h),0b3h,13,10
  db 7  dup(0b0h),0c0h,34 dup(0c4h),0d9h,13,10,"$"
 sprava1 
db "Zadaj niektoré çíslo (1-4)",13,10," $" 
  ;-----------------------------------------------------------------------------------------
 .code

 start 
 proc
  mov ax, @data
  mov ds, ax
  .SALL
  ROLL 0,0,0,24,79,7                                       ;cls
 menu:  ROLL 8,4,7,0bh,02ah,70h                              ;okno
  LOCATE 4,0
  PROMPT sprava
  call getnum
  push ax
  call rozhod
  pop ax
  jmp menu
 start 
 endp
  ;---------------------------------
 rozhod 
 proc 
  xor ah, ah
  sub al, 31h
  cmp al, 3
  ja error
  cbw
  mov di, ax
  shl di, 1
  jmp vyber (di)
  ;--------------------------------- 
  .LALL
 prog1:  VYPLN 3
  ret
  .SALL
 prog2:  VYPLN 0eh
  ret
 prog3:  VYPLN 0b0h
  ret
 error:  PROMPT sprava1
  ret
 koniec:  mov ah, 4ch
  int 21h
 rozhod 
endp
  ;---------------------------------
 getnum 
 proc
 getnum1: mov ah, 0
  int 16h
  cmp al, 30h
  jb getnum1
  cmp al,39h
  ja getnum1
  ret
 getnum 
 endp
 end 
 start

A15_6.asm

Operátor ENDIF testuje podmienku či bol parameter deklarovaný ako EXTRN. Pri každom vstupe do makra sa inkrementuje pole CNTR, ktoré má len dočasný význam a slúži na kontrolu pri rozvoji makra. Vždy na začiatku je CNTR=0 a po úspešnom vykonaní je CNTR=1. Na konci test CNTR : IF CNTR ; =>

  • Ak CNTR<>0 tak EXITM vygeneruje komentár a zakončí makro.
  • Ak je CNTR=0 cez ENDIF pokračuje v rozvíjaní makra.
 
  A15_6.asm na použitie IFNDEF na test či existujú operandy , 
ďalej podmienku IF či treba makro rozvinut v prípade neexistujúcich operandov.
  ;---------------------------------------------------------------
  if1
  include c:\jazyky\asm\asmexp\abel\macro.lib
  endif
   
  purgeprompt                                ;vymaže nepoužité macro
  ;---------------------------------------------------------------
   
  DIVIDE MACRO dividend,divisor,quotient
  LOCAL COMP
  LOCAL OUT
  CNTR =0                   ;zadefinujem si podmienku
                                                    ;AX=div'd, BX=divisor, CX=quotient 
                                                    ;Delenie postupnym odcitavanim.
                                                     ;Zvysok v AX
  IFNDEF DIVIDEND      ;či definovaný dividend
  CNTR =CNTR+1
  ENDIF
  IFNDEF DIVISOR       ;či definovaný divisor
  CNTR =CNTR+1
  ENDIF
  IFNDEF QUOTIENT   ;či definovaný quotient
  CNTR =CNTR+1
  ENDIF
  IF CNTR                   ; zakončiť makro ak CNTR<0
  EXITM
  ENDIF                                        ;=> možno makro rozvinúť
   
  mov ax, dividend                          ;nastav dividend
  mov bx, divisor                            ;nast divisor
  sub cx, cx                                   ;clear quotient
 COMP:
  cmp ax, bx                                  ;div'd<div'r?
  jb out                                          ;ano exit
  sub ax, bx                                   ;div'd-div'r
  inc cx                                          ;+1 do quotient
  jmp comp
  OUT:
  mov quotient, cx                           ;uloz quotient
  ENDM
  ;-----------------------------------------------------------------
   
 sstack 
segment para stack 'STACK'
  dw    32 dup(?)
 sstack 
ends
  ;--------------------------------------------------------------
   
 data 
segment para "DATA"
 DIVDND 
dw   150                        ;delenec
 DIVSOR 
dw   27                          ;delitel
 QUOTNT 
dw   ?                           ;vysledok
 DATA 
ends
  ;---------------------------------------------------------------
   
 CSEG 
SEGMENT para "code" 
 Start 
proc far
  .SALL                                                     ;potlačí rozvoj makier
  INIT cseg,data,sstack                               ;makro z macro.lib
  .LALL ;rozvinie all
  DIVIDE DIVDND, DIVSOR, QUOTNT         ;operandy OK
  DIVIDE DIDND, DIVSOR, QUOT               ;neexist operandy
  Ret
 start 
endp
 cseg 
ends
 END 
start                                                        ;Navestie pre 1 instr! 
 
---------------------------------------------------------------------------------------
Listing časti A15_6.lst priklad na použitie podmienok s IF a IFNDEF
 
46 0000     CSEG SEGMENT para "code"
47 0000     Start proc far
48             INIT cseg,data,sstack   ;MACRO
49             DIVIDE DIVDND,DIVSOR,QUOTNT 
                                                            ;operandy OK
1 50 = 0000                CNTR =0             ;zadefinujem si podmienku
1 51                                           ;AX=div'd, BX=divisor, CX=quotient
1 52                                      ;Delenie postupný odčtiavanim . Zvyšok v AX
1 53 000B A1 0000r         mov ax, DIVDND     ;nastav DIVDND
1 54 000E 8B 1E 0002r      mov bx, DIVSOR     ;nast DIVSOR
1 55 0012 2B C9            sub cx, cx         ;clear QUOTNT
1 56 0014 3B C3     ??0000:cmp ax,bx          ;div'd<div'r?
1 57 0016 72 05            jb ??0001          ;ano exit
1 58 0018 2B C3            sub ax,bx          ;div'd-div'r
1 59 001A 41               inc cx             ;+1 do QUOTNT
1 60 001B EB F7            jmp ??0000
1 61 001D 89 0E 0004r ?0001:mov QUOTNT, cx     ;uloz QUOTNT
                                         
62                    DIVIDE DIDND,DIVSOR,QUOT 
                                                                                             ;neexist. operandy
1 63 = 0000                                  CNTR =0                       ;zadefinujem si podmienku
1 66                                                                                     ;nedefinovaný DIDND
1 67 = 0001                                  CNTR =CNTR+1
1 68                                                                                      ;nedefinovaný QUOT
1 69 = 0002                                  CNTR =CNTR+1
1 70                                                                                       ;Zakončenie makra
1 71                                               EXITM
72 0021 CB                                  ret                               ;koniec procedúry
73 0022                                        start endp
74 0022                                        cseg ends

 
[Návrat]