Ú-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] |
|
|

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:

- 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):
Poprípade niekoľkých modulov (jano.obj,
data1.obj,
data2.obj), ktoré majú ako hlavný program jano.obj:

- 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:

- 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:
- dát, segmentov a procedúr,
externých
odkazov;
- riadenia výpisu listingu;
- 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:
- 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 |
3 |
;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, |
0 |
;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, |
1 |
;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
1 |
CSEG
|
SEGMENT
para |
PUBLIC
"code" |
2 |
|
|
;Public spoji cseg - sbr a
prg. |
3 0000 |
SUBMUL
|
proc
far |
|
4 |
Assume
|
CS:CSEG |
|
5 |
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š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! |

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 |

|
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. |
F .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 |

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. |
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:
- zopakovalo by výpis makier na
začiatku
programu a
potom
- 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 |

|