Dynamiczna alokacja pamięci

Już w średnio zaawansowanych programach pojawia się potrzeba dynamicznego rezerwowania pamięci. Na przykład, użytkownik podaje nam rozmiar tablicy a my musimy taką tablicę utworzyć i na niej operować (nie znając wcześniej nawet maksymalnego jej rozmiaru). Rozwiązaniem takich problemów jest właśnie dynamiczna alokacja pamięci.

Pod DOSem pamięć alokuje się funkcją AH=48h przerwania 21h, w BX podając liczbę paragrafów do zaalokowania (1 paragraf = 16 bajtów). Jeśli alokacja pamięci się powiedzie, w AX otrzymujemy numer segmentu z zarezerwowaną dla nas pamięcią. Programy typu .com z założenia zajmują całą dostępną pamięć, więc aby coś zaalokować, należy najpierw trochę pamięci zwolnić.

Zwalnianie pamięci wykonuje się funkcją 49h, w ES podając numer segmentu do zwolnienia.

Jak widać, teoria nie jest skomplikowana. Przejdźmy więc może do przykładu. Ten krótki programik ma za zadanie zaalokować 160 bajtów, wyzerować je i na końcu zwolnić.


(przeskocz program)
; Dynamiczna alokacja pamięci 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 środowiskowych
	int	21h		; zwalniamy

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

	mov	ah, 48h		; rezerwuj pamięć
	mov	bx, 10		; 10 paragrafów
	int	21h
	jc	problem		; CF=1 oznacza błąd

	mov	es, ax		; ES = przydzielony segment

	mov	ah, 9
	mov	dx, info
	int	21h		; wyświetl pierwszy napis

	mov	cx, 160		; tyle bajtów wyzerujemy
	xor	di, di		; poczynając 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 pamięć
	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 mieć zadeklarowany stos
section stack stack
	resb 400h

Zwalnianie pamięci w programach typu .com polega na zmianie rozmiaru segmentu kodu. Wykonuje się to funkcją AH=4Ah przerwania 21h, w ES podając segment, którego rozmiar chcemy zmienić (nasz segment kodu - CS), a w BX - nowy rozmiar w paragrafach.
Typowy kod wygląda więc tak:

	mov	ax, cs
	mov	es, ax		; będziemy zmieniać rozmiar segmentu kodu
	mov	bx, koniec	; BX = rozmiar segmentu kodu
	shr	bx, 4		; BX /= 16 - rozmiar w paragrafach
	inc	bx		; +1, żeby nie obciąć naszego programu
	mov	ah, 4ah		; funkcja zmiany rozmiaru
	int	21h

UWAGA: Etykieta koniec musi być ostatnim elementem w kodzie programu.

Jeśli potrzeba więcej pamięci, niż DOS może nam zaoferować, można wykorzystać pamięć EMS lub XMS, o czym piszę w moim mini-kursie o korzystaniu z EMS i XMS.



Spis treści off-line (Alt+1)
Spis treści on-line (Alt+2)
Ułatwienia dla niepełnosprawnych (Alt+0)