Ľudmila Jánošíková

Programovanie v jazyku symbolických adries

pre 32-bitové procesory Intel
Obsah Index
Štandardné segmentové direktívy

Definovanie segmentov pomocou štandardných segmentových direktív je zložitejšie ako so zjednodušenými segmentovými direktívami. Avšak na druhej strane štandardné segmentové direktívy dovoľujú nastaviť rôzne parametre segmentov, napr. určiť, na akej adrese má segment začínať. Skôr, ako pristúpime k popisu jednotlivých direktív, ukážeme rámec programu pri použití štandardných segmentových direktív:

Zasobnik SEGMENT para stack ’stack’
        DB 100h dup (?)
Zasobnik ENDS

Data SEGMENT word public ’data’
; tu sú definované konštanty a premenné
...
Data ENDS

Program SEGMENT word public ’code’
        ASSUME cs:Program, ds:Data, ss:Zasobnik
Zac:    mov ax,Data
        mov ds,ax
        ...
        mov ah,4Ch
        int 21h
Program ENDS

END Zac

Začiatok segmentu definuje direktíva

meno_segmentu SEGMENT [align] [combine] [use] [class]

Význam nepovinných parametrov je nasledujúci:

Parameter align (zarovnanie) určuje, na akej adrese bude segment začínať. Môže nadobúdať hodnoty:

  • byte – segment začne na nasledujúcej slabike. Fyzická adresa segmentu bude mať tvar XXXXXh, kde X je ľubovoľné číslo. Možno vás prekvapí, že adresa nemá na poslednom mieste nulu (bázovú adresu sme vynásobili 16-timi a pripočítali offset, ktorý je na začiatku segmentu nulový – alebo nie je?). Presne tak, ak má segment zarovnanie byte, nemusí byť offset prvého bajtu v segmente 0. Napr. definujme segmenty:

    Data SEGMENT byte
            Cisla DW 0,1,2
    Data ENDS

    Program SEGMENT byte
    ...

    Zarovnanie byte spôsobí, že kódový segment bude začínať hneď na nasledujúcej slabike za dátovým segmentom. Pretože dáta v tomto príklade zaberajú len 6 bajtov, budú bázové adresy obidvoch segmentov rovnaké (napr. 6F5Fh) a offset prvej inštrukcie v programe bude IP = 0006h. Fyzická adresa kódového segmentu teda bude 6F5F6h.

  • word – segment začne na najbližšom slove. Fyzická adresa začiatku segmentu bude XXXXYh, kde Y je párne číslo.
  • dword – segment začne na najbližšom dvojslove. Fyzická adresa začiatku segmentu bude deliteľná štyrmi.
  • para – segment začne na najbližšom paragrafe (1 paragraf = 16 bajtov). Toto je implicitné nastavenie, ktoré majú segmenty, keď neuvedieme parameter align. Fyzická adresa začiatku segmentu bude XXXX0h. Keď teda v predchádzajúcom príklade vynecháme parameter align v direktívach SEGMENT, bude bázová adresa kódového segmentu o 1 väčšia než bázová adresa dátového segmentu (CS = 6F60h) a offset prvej inštrukcie v programe bude IP = 0000h. Fyzická adresa kódového segmentu teda bude 6F600h.
  • page – segment začne na nasledujúcej stránke (1 stránka = 256 bajtov). Fyzická adresa začiatku segmentu bude XXX00h.

Segmenty definované pomocou zjednodušených direktív majú zarovnanie para.

Parameter combine (typ spojenia) určuje, či a akým spôsobom bude spojovací program (linker) spájať daný segment so segmentami rovnakého mena z iných modulov. Parameter combine môže nadobúdať hodnoty:
  • private – implicitná hodnota parametra; znamená, že segment sa spájať nebude.
  • public – všetky public segmenty s rovnakým menom ako má tento segment sa spoja do jedného segmentu. V 16-bitovom režime nesmie byť tento výsledný segment dlhší ako 64 kB. Typ public použijeme pri dátových segmentoch v rôznych moduloch, ak chceme, aby dáta jedného modulu boli prístupné z iného modulu.
  • stack – segmenty typu stack sa spájajú rovnakým spôsobom ako public. Typ stack spôsobí, že bázová adresa výsledného segmentu sa automaticky uloží do registra SS a ukazovateľ zásobníka SP sa nastaví na koniec tohto segmentu. Spojovací program vyžaduje, aby program mal aspoň jeden stack segment.
  • common – všetky common segmenty s rovnakým menom ako má tento segment budú začínať na rovnakej adrese (budú sa prekrývať). Výsledný segment bude mať takú dĺžku, ako má najdlhší zo spojených common segmentov. Typ common má zmysel vtedy, keď všetky moduly používajú rovnaký segment, napr. segment s dátami:

    Data SEGMENT common
    ; definícia spoločných dát
    ...
    Data ENDS

    Tento spoločný segment umiestnime do samostatného súboru a potom ho pomocou direktívy

    INCLUDE meno_súboru

    včleníme do všetkých modulov, ktoré tieto spoločné dáta potrebujú. Vyhneme sa tak odkazom na externé dáta.

  • memory – to isté ako common.
  • at výraz – segment (musí byť para) sa umiestni na absolútnu adresu danú výrazom. Používa sa v reálnom režime pri prístupe k údajovým štruktúram BIOS-u v pamäti ROM, k video pamäti, a pod.

Obr. 20 ilustruje rôzne spôsoby spojenia pre segmenty rovnakého mena s  parametrom combine z dvoch rôznych modulov A a B.

pred spojením
po spojení
A

B
private
A

B


A

B
public, stack
A
B

A

B
common, memory
A B


Obr. 20. Spôsoby spojenia segmentov

Zjednodušené segmentové direktívy definujú pre dátový a kódový segment typ spojenia public, pre zásobníkový segment typ stack.

Parameter use nastavuje dĺžku offsetu:
  • use16 – offset bude mať 16 bitov (implicitná hodnota);
  • use32 – offset bude mať 32 bitov.

Pri použití zjednodušených segmentových direktív závisí dĺžka offsetu od poradia direktívy .MODEL a direktív, ktoré sprístupňujú inštrukčný súbor daného procesora (sú to direktívy .386, .486, .586). Ak najprv uvedieme .MODEL a potom napr. .386, budú mať všetky segmenty 16-bitový offset. Ak použijeme opačné poradie (najprv .386, potom .MODEL), budú mať všetky segmenty 32-bitový offset.

Parameter class (trieda) je reťazec v apostrofoch; určuje, v akom poradí budú segmenty zoradené v .EXE súbore. Spojovací program umiestni všetky segmenty jednej triedy za sebou. Poradie tried sa určuje podľa poradia tried v prvom .OBJ súbore, poradie segmentov v rámci jednej triedy potom podľa poradia .OBJ súborov pri spájaní. Napr. ak spájame súbory ZACIATOK.OBJ, POKRAC.OBJ, KONIEC.OBJ do súboru CELY.EXE a poradie segmentov podľa tried v jednotlivých súboroch je:

ZACIATOK.OBJ: ‘data’, ‘code’, ‘stack’

POKRAC.OBJ: ‘stack’, ‘data’, ‘code’

KONIEC.OBJ: ‘data’, ‘code’

tak výsledné poradie segmentov v CELY.EXE bude: ‘data’, ‘code’, ‘stack’. Poradie segmentov v .OBJ súbore možno ovplyvniť direktívami

.SEQ (implicitne) – segmenty v .OBJ súbore budú v takom poradí, ako sú uvedené v zdrojovom texte;

.ALPHA – segmenty sa zoradia v abecednom poradí podľa mien (nie podľa tried!).

Ak spájate assemblerovský program s programom vo vyššom jazyku, rozhoduje o poradí segmentov prekladač vyššieho jazyka. V čistých assemblerovských programoch môžete použiť direktívu DOSSEG, ktorá zoradí segmenty podľa pravidiel Microsoftu: ‘code’, ‘data’, ‘stack’. Toto poradie sa použije tiež pri zjednodušených direktívach.

Nasledujúca tabuľka ukazuje implicitné segmentové atribúty, ktoré sa priradia segmentom, ak sme použili zjednodušené segmentové direktívy a pamäťový model small.

Tabuľka 8
Implicitné segmenty v pamäťovom modeli small
Direktíva Meno segmentu Zarovnanie Typ spojenia Trieda
.CODE _TEXT para public 'code'
.DATA _DATA para public 'data'
.STACK STACK para stack 'stack'

Keď deklarujeme segmenty pomocou štandardných segmentových direktív, prekladač nemôže vedieť, ktorý segment obsahuje inštrukcie, ktorý dáta a ktorý zásobník. Preto pomocou direktívy ASSUME alebo pomocou operátora prepisu segmentu musíme prekladaču oznámiť, pomocou ktorých segmentových registrov sú segmenty adresované.

Direktíva ASSUME spája segmentové registre s menami segmentov, ale neukladá do segmentových registrov bázové adresy segmentov, to je rovnako ako pri zjednodušených direktívach záležitosť operačného systému (pre segmentové registre CS a SS), resp. programátora (pre ostatné segmentové registre). Direktíva ASSUME so segmentovým registrom CS sa musí objaviť pred prvou inštrukciou programu, aby prekladač vedel, ktorý segment sa má použiť v štartovacej adrese programu, pri skokoch a volaniach procedúr. ASSUME s ostatnými segmentovými registrami sa môže vyskytovať kdekoľvek v programe, ale pred prvým prístupom do daného segmentu. V direktíve ASSUME sa môžu vyskytovať predpokladané priradenia pre jeden alebo viac segmentových registrov. Priradenie segmentov segmentovému registru môžeme v priebehu programu meniť (ak pritom samozrejme zmeníme aj obsah segmentového registra). Pozrime si nasledujúci program:

Data1 SEGMENT

Prem DW ?
Data1 ENDS

Data2 SEGMENT

Cislo DW 0
Data2 ENDS

Program SEGMENT
ASSUME ds:Data1, cs:Program
Zac:    mov ax,Data1
        mov ds,ax
        mov ax,[Cislo]

Na poslednom príkaze prekladač vyhlási chybu, lebo premenná Cislo je definovaná v segmente Data2, avšak tento segment nie je spojený so žiadnym segmentovým registrom. Chybu hneď napravíme:

ASSUME es:Data2
        mov ax,Data2
        mov es,ax
        mov ax,[Cislo]

Teraz je všetko v poriadku. V direktíve ASSUME es:Data2 sme prekladaču oznámili, že segment Data2 je adresovaný pomocou segmentového registra ES a prekladač automaticky doplní prepis segmentu:

        mov ax,es:[Cislo]

Ak budeme pokračovať v príklade, môžeme zmeniť priradenie pre segmentový register DS a naplniť ho bázovou adresou segmentu Data2:

ASSUME ds:Data2
        push es
        pop ds
        mov ax,[Cislo]

V tomto prípade v poslednej inštrukcii nepotrebujeme prepis segmentu, lebo segmentový register DS sa implicitne používa pri odkazoch na dáta. Pokračujme v príklade a zmeňme obsah registra DS:

        mov ax,Data1
        mov ds,ax
        mov ax,[Cislo]

Pretože sme nezmenili priradenie segmentu segmentovému registru DS, prekladač sa domnieva, že priradenie ds:Data2 stále platí a pri prístupe k premennej Cislo použije segmentový register DS, ktorý však už neobsahuje adresu Data2. Táto chyba sa prejaví pri vykonávaní programu.

Direktíva

ASSUME nothing

zruší priradenie vytvorené poslednou direktívou ASSUME. Direktíva

ASSUME segmentový_register:nothing

zruší posledné priradenie danému segmentovému registru.

Direktíva ASSUME nie je povinná, ale ak ju neuvedieme, musíme pri každom odkaze na pamäť použiť prepis segmentu.

Hore

Načo je vám jazyk symbolických adries?

Architektúra moderných procesorov

Registre

Spôsoby adresovania

Premenné a návestia

Symbolické konštanty

Inštrukčný súbor

Segmentové direktívy

Moduly

Služby operačného systému MS-DOS

Služby operačného systému Windows 95/98/NT/XP

Systémová úroveň vstupu a výstupu

Prostriedky pre prípravu programu

Segmentové direktívy | Moduly
Vydala Žilinská univerzita v Žiline, 2000. ISBN 80-7100-723-4.
Otázky a pripomienky môžete poslať autorke.
Naposledy upravené 29.10.2007.