Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

DOS_MEM.ASM

Obsluha paměti


; ============================================================================
;
;                            LT-DOS - Int 21h memory
;
; ============================================================================

; ------------- Memory Control Block, MCB

struc		MCB

MCB_Type:	resb	1	; 0: block type (see below)
MCB_Owner:	resw	1	; 1: PSP segment of owner or flag (see below)
MCB_Size:	resw	1	; 3: size of block in paragraphs
MCB_Res:	resb	3	; 5: ...reserved
MCB_Name:	resb	8	; 8: ASCII program name (nul terminated if < 8)

endstruc

MCB_SIZE	EQU	MCB_size	; 10h (=16) bytes

; ------------- MCB block type

MCBTypeLast	EQU	5Ah	; last block in chain (="Z")
MCBTypeMid	EQU	4Dh	; middle block in chain ("M")

; ------------- MCB owner flag (in MCB_PSP)

MCBOwnerFree	EQU	0	; free block
MCBOwnerSys	EQU	8	; system

; ------------- Allocation strategy

MEMFIRSTFIT	EQU	0	; memory first fit
MEMBESTFIT	EQU	1	; memory best fit
MEMLASTFIT	EQU	2	; memory last fit

; ----------------------------------------------------------------------------
;                               Find next MCB
; ----------------------------------------------------------------------------
; INPUT:	SI = 0 (to optimize program)
;		DS = segment of MCB header
; OUTPUT:	CF = (NC) clear if valid MCB
;			DS = segment of next MCB
;		CF = (CY) set on error, MCB is invalid		
; DESTROYS:	AX
; ----------------------------------------------------------------------------

NextMCB:	mov	ax,ds		; AX <- segment of MCB
		inc	ax		; skip MCB header
		add	ax,[si+MCB_Size]; skip MCB size
		mov	ds,ax		; DS <- segment of next MCB
		jc	TestMCB2	; error, overflow 1 MB boundary

; --- TestMCB function must follow!

; ----------------------------------------------------------------------------
;                Test validity of MCB (Memory Control Block)
; ----------------------------------------------------------------------------
; INPUT:	SI = 0 (to optimize program)
;		DS = segment of MCB header
; OUTPUT:	CF = (NC) clear if valid MCB
;		CF = (CY) set on error, MCB is invalid		
; ----------------------------------------------------------------------------

TestMCB:	cmp	byte [si+MCB_Type],MCBTypeMid ; is it middle MCB?
		je	TestMCB2	; it is middle MCB
		cmp	byte [si+MCB_Type],MCBTypeLast ; is it last MCB?
		je	TestMCB2	; it is last MCB
		stc			; set error flag
TestMCB2:	ret

; ----------------------------------------------------------------------------
;                          Coalesce free MCBs
; ----------------------------------------------------------------------------
; INPUT:	SI = 0 (to optimize program)
;		DS = segment of first free MCB header
; OUTPUT:	CF = (NC) clear if valid MCB
;		CF = (CY) set on error, MCB is invalid		
; DESTROYS:	AX, ES
; ----------------------------------------------------------------------------

; ------------- Check if it is last MCB

CoalesceMCB:	cmp	byte [si+MCB_Type],MCBTypeLast ; is it last MCB?
		je	TestMCB2	; it is last MCB (here is NC)

; ------------- Find next MCB (-> ES)

		push	ds		; push DS
		call	NextMCB		; find next MCB
		push	ds		; push DS
		pop	es		; ES <- segment of next MCB
		pop	ds		; pop DS
		jc	TestMCB2	; error

; ------------- Check if it is free MCB (else return with NC)

		cmp	[es:si+MCB_Owner],si ; free MCB?
		jne	TestMCB2	; it is not free MCB (here is NC)

; ------------- Coalesce MCBs

		mov	ax,[es:si+MCB_Size]; AX <- size of coalesced MCB
		inc	ax		; add size of MCB header
		add	[si+MCB_Size],ax ; increase size of this MCB

; ------------- Transfer type of MCB

		mov	al,[es:si+MCB_Type]; AL <- type of coalesced MCB
		mov	[si+MCB_Type],al ; transfer type of MCB
		jmp	short CoalesceMCB ; coalesce next MCB

; ----------------------------------------------------------------------------
;                  Free memory blocks of one owner
; ----------------------------------------------------------------------------
; INPUT:	AX = owner
; DESTROYS:	SI
; ----------------------------------------------------------------------------

; ------------- Test first allocated block

FreeOwner:	xor	si,si		; SI <- 0 (to optimize program)
		mov	ds,[FirstAlloc]	; DS <- first allocated block
		call	TestMCB		; test first MCB
FreeOwner2:	jc	TestMCB2	; invalid MCB

; ------------- Check if it is this owner

		cmp	[si+MCB_Owner],ax ; is it this owner?
		jne	FreeOwner4	; it is not this owner
		mov	[si+MCB_Owner],si ; mark this MCB as free

; ------------- Find next MCB

FreeOwner4:	cmp	byte [si+MCB_Type],MCBTypeLast ; is it last MCB?
		je	TestMCB2	; it is last MCB
		call	NextMCB		; find next MCB
		jmp	short FreeOwner2

; ----------------------------------------------------------------------------
;                 Int 21h, function 48h - Allocate memory
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 48h (function code)
;		BX = number of paragraphs to allocate
; INT21 OUTPUT:	CF = (NC) clear if successful
;			AX = segment of allocated block
;		CF = (CY) set on error
;			AX = error code
;				7: memory control block damaged
;				8: insufficient memory
;			BX = size of largest available block
; ----------------------------------------------------------------------------

; ------------- Init pointers

Int2148:	xor	si,si		; SI <- 0 (to optimize program)
		push	cs		; push CS
		pop	ds		; DS <- CS
		xor	ax,ax		; AX <- 0
		mov	[FirstMem],ax	; reset first found block
		mov	[SmallMem],ax	; reset smallest suitable block
		mov	[LastMem],ax	; reset last found block
		xchg	ax,di		; DI <- 0 max. size of block

; ------------- Test first allocated block

		mov	ds,[FirstAlloc]	; DS <- first allocated block
		call	TestMCB		; test first MCB
		jc	Int2148MCBErr	; invalid first MCB

; ------------- Check if it is free MCB

Int21481:	cmp	[si+MCB_Owner],si ; free MCB?
		jne	Int21486	; it is not free MCB

; ------------- Found free block, coalesce following free MCBs

		call	CoalesceMCB	; coalesce free MCBs
		jc	Int2148MCBErr	; error, damaged MCB

; ------------- Check if it is bigger block

		mov	ax,[si+MCB_Size]; AX <- size of this MCB
		cmp	ax,di		; is it bigger block?
		jbe	Int21482	; it is not bigger block
		mov	di,ax		; DI <- size of largest block

; ------------- Check if this block satisfies

Int21482:	cmp	ax,bx		; is this block big enough?
		jb	Int21486	; this block is not big enough

; ------------- Store first found block

		cmp	[cs:FirstMem],si ; is it first block?
		jne	Int21483	; first block was already found
		mov	[cs:FirstMem],ds ; store first found block

; ------------- Store smallest suitable block

Int21483:	cmp	[cs:SmallMem],si ; smallest block found?
          	je	Int21484	; smallest block not found
		mov	es,[cs:SmallMem] ; ES <- smallest block
		cmp	ax,[es:si+MCB_Size] ; found smaller block?
		jae	Int21485	; it is not smaller block		
Int21484:	mov	[cs:SmallMem],ds ; store smallest suitable block

; ------------- Store last found allocated block

Int21485:	mov	[cs:LastMem],ds	; store last found allocated block

; ------------- Check, if it is last MCB

Int21486:	cmp	byte [si+MCB_Type],MCBTypeLast ; is it last MCB?
		je	Int21487	; it is last MCB

; ------------- Find next MCB

		call	NextMCB		; find next MCB
		jnc	Int21481	; test next MCB

; ------------- Invalid MCB

Int2148MCBErr:	mov	al,DOSERR_MCBERR ; AL <- 7 error, damaged MCB
Int2148Err:	jmp	DOSError	; set DOS error

; ------------- End of memory reached, test if any MCB was found

Int21487:	mov	ax,[cs:FirstMem] ; AX <- first found block
		or	ax,ax		; any MCB found?
		xchg	ax,di		; AX <- max. size, DI <- first block
		je	Int214A2	; error, insufficient memory

; ------------- Prepare address of found MCB (-> DS, SI)

		cmp	byte [cs:MemStrategy],1 ; use best fit block?
		ja	Int2148A	; use last found block
		jb	Int21488	; use first found block
		mov	di,[cs:SmallMem] ; DS <- smallest block
Int21488:	mov	ds,di		; DS <- segment of found block

; ------------- Size of rest of block

Int214882:	mov	ax,[si+MCB_Size]; AX <- size of block
		sub	ax,bx		; AX <- rest of block size
		jz	Int21489	; no block lefts
		dec	ax		; without header

; ------------- Split block into two parts

		mov	dx,ds		; DX <- segment of block
		inc	dx		; skip header of block
		add	dx,bx		; skip data of block
		mov	es,dx		; ES <- segment of next block
Int214884:	mov	[es:si+MCB_Size],ax ; size of second block
		mov	[si+MCB_Size],bx ; set new size of first block

; ------------- Mark blocks

		mov	al,MCBTypeMid	; AL <- mark of middle block
		xchg	al,[si+MCB_Type] ; mark this block as middle
		mov	[es:si+MCB_Type],al ; transfer mark to next block
		mov	ax,es		; AX <- second block
		cmp	ax,di		; is it new block?
		je	Int21489	; it is new block
		mov	[es:si+MCB_Owner],si ; mark block as free
		mov	[es:si+MCB_Name],si ; no valid name of block

; ------------- Set owner of new MCB

Int21489:	mov	ds,di		; DS <- segment of MCB
		mov	ax,[cs:CurrentPSP] ; AX <- current PSP
		mov	[si+MCB_Owner],ax; owner of this MCB

; ------------- Segment of new MCB

		xchg	ax,di		; AX <- segment of found block
		inc	ax		; skip header of MCB
		jmp	DOSOK		; clear CF

; ------------- Use last found allocated block (use end of block)

Int2148A:	mov	ds,[cs:LastMem]	; DS <- last memory
		mov	di,ds		; DI <- segment of found block
		mov	ax,[si+MCB_Size]; AX <- size of block
		sub	ax,bx		; AX <- rest of block size
		jz	Int21489	; no block lefts
		add	di,ax		; DI <- next block
		mov	es,di		; ES <- next block
		dec	ax		; size without header
		xchg	ax,bx		; AX <- MCB 2 size, BX <- MCB 1 size
		jmp	short Int214884

; ----------------------------------------------------------------------------
;                   Int 21h, function 4Ah - Resize memory
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 4Ah (function code)
;		BX = new size of memory block
;		ES = segment of block to resize
; INT21 OUTPUT:	CF = (NC) clear if successful
;		CF = (CY) set on error
;			AX = error code
;				7: memory control block damaged
;				8: insufficient memory
;				9: memory block address invalid
;			BX = maximum available size of block
; NOTES: If there is insufficient memory to expand the block, the block will
;	 be made as large as possible and BX returns new size of the block
; ----------------------------------------------------------------------------

; ------------- Prepare address of MCB

Int214A:	xor	si,si		; SI <- 0 (to optimize program)
		mov	ax,es		; AX <- segment of MCB
		dec	ax		; AX <- segment of MCB header
		mov	ds,ax		; DS <- segment of MCB
		xchg	ax,di		; DI <- segment of MCB

; ------------- Test MCB

		call	TestMCB		; test first MCB
		jc	Int21492	; error, invalid address

; ------------- Coalesce following free MCBs

		call	CoalesceMCB	; coalesce free MCBs
		jc	Int21494	; error, damaged MCB

; ------------- Check new size of MCB

		mov	ax,[si+MCB_Size]; AX <- size of MCB
		cmp	ax,bx		; check MCB size
		jae	Int214882	; MCB size is OK

; ------------- Error, insufficient memory

Int214A2:	xchg	ax,bx		; BX <- new size of MCB
		call	SetRegBX	; set register BX (new size of MCB)
		mov	al,DOSERR_MEMORY ; AL <- error 8, insufficient memory
		jmp	short Int21581	; error, insufficient memory

; ----------------------------------------------------------------------------
;                   Int 21h, function 49h - Free memory
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 49h (function code)
;		ES = segment of block to free
; INT21 OUTPUT:	CF = (NC) clear if successful
;		CF = (CY) set on error
;			AX = error code
;				7: memory control block damaged
;				9: memory block address invalid
; ----------------------------------------------------------------------------

; ------------- Prepare address of MCB

Int2149:	xor	si,si		; SI <- 0 (to optimize program)
		mov	ax,es		; AX <- segment of MCB
		dec	ax		; AX <- segment of MCB header
		mov	ds,ax		; DS <- segment of MCB

; ------------- Test MCB

		call	TestMCB		; test first MCB
Int21492:	mov	al,DOSERR_ADDRESS ; AL <- error 9, invalid address
		jc	Int21581	; error, invalid address

; ------------- Mark MCB as free

		mov	word [si+MCB_Owner],si ; mark MCB as free

; ------------- Coalesce following free MCBs

		call	CoalesceMCB	; coalesce free MCBs
Int21494:	mov	al,DOSERR_MCBERR ; AL <- error 7, MCB damaged
		jc	Int21581	; error, damaged MCB
		jmp	short Int21586	; return OK

; ----------------------------------------------------------------------------
;          Int 21h, function 58h - Get or set allocation strategy
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 58h (function code)
;		AL = subfunction
;			0 = get allocation strategy
;			1 = set allocation strategy
;		if subfunction 1:
;		BL = new allocation strategy (see Allocation strategy)
; INT21 OUTPUT:	CF = (NC) clear if successful
;		if subfunction 0:
;			AX = current strategy (see Allocation strategy)
;		CF = (CY) set on error
;			AX = error code
;				1: function number invalid
; ----------------------------------------------------------------------------

; ------------- Test subfunction code

Int2158:	cmp	al,1		; set allocation strategy?
		je	Int21584	; set allocation strategy
		jb	Int21582	; get allocation strategy

; ------------- Error - invalid subfunction code

		mov	al,DOSERR_INVFUNC ; AL <- error, invalid function
Int21581:	jmp	DOSError	; set CF

; ------------- Get allocation strategy

Int21582:	mov	ah,0		; AH <- 0
		mov	al,[cs:MemStrategy] ; AL <- current strategy
		jmp	short Int21586	; return OK

; ------------- Set allocation strategy
		
Int21584:	mov	[cs:MemStrategy],al ; set allocation strategy
Int21586:	jmp	DOSOK		; return OK

; ----------------------------------------------------------------------------
;                                    Data
; ----------------------------------------------------------------------------

FirstMem:	dw	0		; first found allocated block
SmallMem:	dw	0		; smallest suitable allocated block
LastMem:	dw	0		; last found allocated block

TopMem:		dw	0a000h		; top of usable memory

MemStrategy:	db	MEMFIRSTFIT	; allocation strategy

Zpět na stránku systému LT-DOS