   #Start Contents

                         Dynamiczna alokacja pamieci

   Juz w srednio zaawansowanych programach pojawia sie potrzeba
   dynamicznego rezerwowania pamieci. Na przyklad, uzytkownik podaje nam
   rozmiar tablicy a my musimy taka tablice utworzyc i na niej operowac
   (nie znajac wczesniej nawet maksymalnego jej rozmiaru). Rozwiazaniem
   takich problemow jest wlasnie dynamiczna alokacja pamieci.

   Pod DOSem pamiec alokuje sie funkcja AH=48h przerwania 21h, w BX
   podajac liczbe paragrafow do zaalokowania (1 paragraf = 16 bajtow).
   Jesli alokacja pamieci sie powiedzie, w AX otrzymujemy numer segmentu
   z zarezerwowana dla nas pamiecia. Programy typu .com z zalozenia
   zajmuja cala dostepna pamiec, wiec aby cos zaalokowac, nalezy najpierw
   troche pamieci zwolnic.

   Zwalnianie pamieci wykonuje sie funkcja 49h, w ES podajac numer
   segmentu do zwolnienia.

   Jak widac, teoria nie jest skomplikowana. Przejdzmy wiec moze do
   przykladu. Ten krotki programik ma za zadanie zaalokowac 160 bajtow,
   wyzerowac je i na koncu zwolnic.
   (przeskocz program)
; Dynamiczna alokacja pamieci pod DOSem
;
; Autor: Bogdan D., bogdandr (at) op.pl
;
; kompilacja:
;
; nasm -f obj -o allocdos.obj allocdos.asm
; val allocdos.obj,allocdos.exe,,,

section .text

..start:
        mov     ah, 49h
        mov     es, [ds:2ch]    ; ES=segment naszych zmiennych srodowiskowych
        int     21h             ; zwalniamy

        mov     ax, seg info
        mov     ds, ax          ; DS = nasz segment danych (w razie czego)

        mov     ah, 48h         ; rezerwuj pamiec
        mov     bx, 10          ; 10 paragrafow
        int     21h
        jc      problem         ; CF=1 oznacza blad

        mov     es, ax          ; ES = przydzielony segment

        mov     ah, 9
        mov     dx, info
        int     21h             ; wyswietl pierwszy napis

        mov     cx, 160         ; tyle bajtow wyzerujemy
        xor     di, di          ; poczynajac od adresu 0 w nowym segmencie
        xor     al, al          ; AL = 0
        cld                     ; kierunek: do przodu
        rep     stosb           ; zerujemy obszar

        mov     ah, 49h
        int     21h             ; zwalniamy pamiec
        jc      problem


        mov     ah, 9
        mov     dx, info2
        int     21h

problem:
        mov     ax, 4c00h
        int     21h

koniec:

section .data

info    db      "Udana alokacja pamieci.",10,13,"$"
info2   db      "Udane zwolnienie pamieci.",10,13,"$"

; program typu .exe musi miec zadeklarowany stos
section stack stack
        resb 400h

   Zwalnianie pamieci w programach typu .com polega na zmianie rozmiaru
   segmentu kodu. Wykonuje sie to funkcja AH=4Ah przerwania 21h, w ES
   podajac segment, ktorego rozmiar chcemy zmienic (nasz segment kodu -
   CS), a w BX - nowy rozmiar w paragrafach.
   Typowy kod wyglada wiec tak:
        mov     ax, cs
        mov     es, ax          ; bedziemy zmieniac rozmiar segmentu kodu
        mov     bx, koniec      ; BX = rozmiar segmentu kodu
        shr     bx, 4           ; BX /= 16 - rozmiar w paragrafach
        inc     bx              ; +1, zeby nie obciac naszego programu
        mov     ah, 4ah         ; funkcja zmiany rozmiaru
        int     21h

   UWAGA: Etykieta "koniec" musi byc ostatnim elementem w kodzie
   programu.

   Jesli potrzeba wiecej pamieci, niz DOS moze nam zaoferowac, mozna
   wykorzystac pamiec EMS lub XMS, o czym pisze w moim mini-kursie o
   korzystaniu z EMS i XMS.

   Spis tresci off-line (klawisz dostepu 1)
   Spis tresci on-line (klawisz dostepu 2)
   Ulatwienia dla niepelnosprawnych (klawisz dostepu 0)
