⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.asm

📁 汇编编程艺术
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;   |prevfree|     |CurFreeBlk| |FollowingBlk|   |NextFreeBlk|
;
; We want to wind up with:
;
;
;        +------------------------------------------+   <-These are dbl links.
;        |                                          |
;   |prevfree|     |CurFreeBlk| |FollowingBlk|   |NextFreeBlk|
;
;
; First, merge the current free block and the following block together.
;
		mov	ax, dsptr.blksize		;Get size of next block.
		add	esptr.blksize, ax		; Join the blocks together.
		mov	ax, dsptr.fwdptr
		mov	esptr.fwdptr, ax
		or	ax, ax
		jz	DontSetBwd
		push	ds
		mov	ds, ax
		mov	dsptr.bwdptr, es
		pop	ds
;
; Make sure that there is a |prevfree| block.
;
DontSetBwd:	mov	ax, dsptr.freebwdptr
		or	ax, ax
		jz	SetFreeSpcPtr
;
; prevfree.fwd := following.fwd;
;
		mov	es, dsptr.freebwdptr	;Point ES at previous guy.
		mov	ax, dsptr.freefwdptr
		mov	esptr.freefwdptr, ax	;Skip over current guy.
;
; If the fwd pointer is NIL, no need to continue.
;
		or	ax, ax			;See if end of list.
		jz	NextBlkNotFree
;
; nextfree.bwd := following.bwd (prevfree).
;
		mov	ax, es			;Save ptr to this guy.
		mov	es, dsptr.freefwdptr
		mov	esptr.freebwdptr, ax
		jmp	short NextBlkNotFree
;
; If FollowingBlk is the first free block in the free list, we have to
; execute the following code.
;
SetFreeSpcPtr:  mov	es, dsptr.freefwdptr
		mov	esptr.freebwdptr, NIL
		mov	StdGrp:FreeSpace, es
;
;
;
; After processing the block following this block, or if the next block
; was not free, come down here and check to see if the previous block
; was free.
;
NextBlkNotFree:	pop	es		;Restore pointer to current block.
		push	es
		mov	ax, esptr.bwdptr
		or	ax, ax		;Is it a NIL pointer
		jz	NoPrevBlock
		mov	ds, ax
		cmp     dsptr.refcnt, 0	;Is that block free?
		jnz	NoPrevBlock
;
; Okay, the block in front is free.  Merge the current block into that one.
;
		mov	ax, esptr.blksize
		add	dsptr.blksize, ax
		mov	ax, esptr.fwdptr
		mov	dsptr.fwdptr, ax
		or	ax, ax			;See if there is a next blk.
		jz	NoNextBlk
		mov	es, ax
		mov	esptr.bwdptr, ds
NoNextBlk:	stc
		pop	es
		pop	ds
		ret
;
NoPrevBlock:	clc
		pop	es
		pop	ds
		ret
Coalesce	endp
;
;
;============================================================================
;
; *****      *******       *      *        *         *****       *****
; *    *     *            * *     *        *        *     *     *     *
; *    *     *           *   *    *        *        *     *     *
; *****      *****       *****    *        *        *     *     *
; *  *       *           *   *    *	   *        *     *     *
; *   *      *           *   *    *        *        *     *     *     *
; *    *     *******     *   *    *****    *****     *****       *****
;
;============================================================================
;
;
; REALLOC - This routine expects a pointer in ES:DI and a new size in CX.
;	    If the specified block is larger than the value in CX then
;	    realloc shrinks the size of the block and returns the left over
;	    information to the system heap.  If CX is larger than the speci-
;	    fied block then realloc allocates a new block and copies the
;	    data from the old block to the new block and then frees the
;	    old block.  In any case, realloc returns a pointer to the
;	    (possibly new) block in ES:DI.  Carry=0 on return if no error,
;	    carry=1 on return if there wasn't enough room on the heap to
;	    reallocate a larger block.
;
		public	sl_realloc
sl_realloc	proc	far
		cmp	di, 8			;Is this a realistic pointer?
		jz	DoREALLOC
		stc				;Return with error, if not.
		ret
;
DoREALLOC:	push	ax 
		push	cx
		push	ds
		push	si
;
;
; Convert byte count to paragraph count, since we always allocate whole
; paragraphs.
;
		add	cx, 8			;We have eight bytes of overhead!
		rcr	cx, 1			;Use rcr because of add above.
		adc	cx, 0
		shr	cx, 1
		adc	cx, 0
		shr	cx, 1
		adc	cx, 0
		shr	cx, 1
		adc	cx, 0
;
; See if the new block size is larger or smaller than the old block size.
;
		cmp	cx, esptr.BlkSize
		ja	MakeBigger
;
; New desired size is less than or equal to the current size.  If no more
; than 32 bytes larger, don't even bother with the operation.
;
		inc	cx
		inc	cx
		cmp	cx, esptr.BlkSize
		jae	ReallocDone
		dec	cx
		dec	cx
;
; Okay, the new block size is seriously smaller here.  Turn the last group
; of bytes into a free block.
;
		mov	ax, es			;Get ptr to block
		add	ax, cx			;Add in new length
		mov	ds, ax			;Point at new block.
		mov	ax, esptr.BlkSize	;Compute the size of the
		sub	ax, cx			; new block.
		mov	dsptr.BlkSize, ax	;Save away the link.
		mov	dsptr.bwdptr, es	;Set up back pointer.
		mov	ax, esptr.fwdptr	;Copy old fwd ptr to new
		mov	dsptr.fwdptr, ax	; fwd ptr.
		mov	dsptr.refcnt, 1		;Init reference count to 1.
		mov	esptr.fwdptr, ds	;Set up new fwd ptr.
		mov	esptr.BlkSize, cx	;Set up new length.
		push	es 
		mov	di, 8
		mov	ax, ds
		mov	es, ax
		call	sl_free			;Free the new block.
		mov	di, 8
		pop	es			;Get pointer to original blk
;
ReAllocDone:	pop	si 
		pop	ds 
		pop	cx
		pop	ax
		clc
		ret
;
;
;
; If they had the nerve to want this block larger, come down here and allocate
; a new block, copy the old data to the new block, and then free the old block.
;
;
MakeBigger:	mov	ax, es			;Preserve pointer to old blk.
		mov	ds, ax
		mov	si, di			;Contains "8".
		call	sl_malloc		;Allocate new block.
		jc	BadRealloc
;
; Okay, copy the old block to the new block.  Note that both SI and DI
; contain 8 at this point.  We can make this assumption here because,
; after all, this is the memory manager code and it knows the internal
; representation.
;
		mov	cx, dsptr.BlkSize	;Get original block size
		shl	cx, 1			;Convert from paragraphs
		shl	cx, 1			; to word count.
		shl	cx, 1
		pushf
		cld
	rep	movsw				;Note we're moving words!
		popf
;
; Okay, free up the old block and we're done.
;
		mov	di, 8
		push	es   			;Save ptr to new block.
		mov	ax, ds
		mov	es, ax
		call	sl_free
		clc
		mov	di, 8			;Restore new block ptr.
		pop	es 
		pop	si 
		pop	ds 
		pop	cx 
		pop	ax
		ret
;
BadRealloc:	stc
		pop	si 
		pop	ds 
		pop	cx 
		pop	ax
		ret
sl_realloc	endp
;
;
;
;
;============================================================================
;
;   ********      *        *     ********    ********    *******   *******
;   *       *     *        *     *       *   *       *      *      *      *
;   *       *     *        *     *       *   *       *      *      *      *
;   *       *     *        *     ********    ********       *      *******
;   *       *     *        *     *           *              *      *   *
;   *       *     *        *     *           *              *      *    *
;   *       *     *        *     *           *              *      *     *
;   ********       ********      *           *              *      *      *
;
;============================================================================
;
;
; Dupptr - Bumps up the reference count for a particular pointer by one.
;	   Returns carry = 1 if initial pointer is illegal, returns carry=0
;	   if no error.  Returns pointer in ES:DI.  You must pass the pointer
;	   to increment in ES:DI.
;
		public	sl_DupPtr
sl_DupPtr	proc	far
		cmp	di, 8			;See if this is a valid ptr.
		je	GoodPtr
		stc
		ret
;
GoodPtr:	inc	esptr.refcnt		;Bump up the reference cnt.
		clc
		ret
sl_DupPtr	endp
;
;
;============================================================================
;
; *****   *****   *****   *   *   *   *   *****     *     *****
;   *     *         *     **      *   *   *        * *    *    *
;   *      ***      *     * * *   *****   ***     *****   *    *
;   *         *     *     *  **   *   *   *       *   *   *****
;   *         *     *     *   *   *   *   *       *   *   *
; *****   *****   *****   *   *   *   *   *****   *   *   *
;
;============================================================================
;
; IsInHeap-	Returns carry clear if the pointer passed in es:di is within
;		the heap.  Returns carry set if this pointer is outside the
;		heap.
;
		public	sl_IsInHeap
sl_IsInHeap	proc	far
		push	ax
		push	bx
		mov	bx, es
		mov	ax, StdGrp:StartOfHeap
		cmp	bx, ax
		jb	Outside
		add	ax, StdGrp:SizeOfHeap
		mov	bx, es
		cmp	bx, ax
		ja	Outside
		clc
		pop	bx
		pop	ax
		ret
;
Outside:	stc
		pop	bx
		pop	ax
		ret
sl_IsInHeap	endp
;
;
;
;
;============================================================================
;
; *****   *****   *****	   *****   *****
;   *     *       *    *     *     *    *
;   *      ***    *****      *     *****
;   *         *   *          *     * *
;   *         *   *          *     *  *
; *****   *****   *          *     *   *
;
;============================================================================
;
; IsPtr-	Returns the carry flag clear if es:di points at the beginning
;		of an allocated block in the heap.  Returns with the carry
;		flag clear if es:di points at a deallocated block.
;
		public	sl_IsPtr
sl_IsPtr	proc	far
		cmp	di, 8 		;All of our ptrs have an offset of 8.
		jne	NotPtr2
		push	ax
		push	bx
		push	es
		mov	ax, es
;
		mov	bx, StdGrp:StartOfHeap
CmpLoop:	cmp	bx, ax
		je	MightBe
		ja	NotPtr
		mov	es, bx
		mov	bx, esptr.fwdptr
		or	bx, bx		;See if NIL link.
		jnz	CmpLoop
;
NotPtr:		pop	es
		pop	bx
		pop	ax
NotPtr2:	stc
		ret
;
; Might be the pointer, let's see if this guy's allocation count is greater
; than zero.
;
MightBe:	mov	es, bx
		cmp	esptr.blksize, 0
		je	NotPtr
		clc
		pop	es
		pop	bx
		pop	ax
		ret
sl_IsPtr	endp






;============================================================================
;
;  *   *   *****     *     ****     ****   *****     *     ****    *****
;  *   *   *        * *    *   *   *         *      * *    *   *     *
;  *   *   *       *   *   *   *   *         *     *   *   *   *     *
;  *****   ****    *****   ****     ***      *     *****   ****      *
;  *   *   *       *   *   *           *     *     *   *   * *       *
;  *   *   *       *   *   *           *     *     *   *   *  *      *
;  *   *   *****   *   *   *       ****      *     *   *   *   *     *
;
;============================================================================
;
; sl_HeapStart-	Returns a pointer to the start of the heap.  Useful for various
; 		operations involving DOS memory management functions (like
;		deallocating the heap).


		public	sl_HeapStart
sl_HeapStart	proc	far
		push	es
		mov	ax, StdGrp
		mov	es, ax
		mov	ax, StdGrp:StartOfHeap
		pop	es
		ret
sl_HeapStart	endp
;
;
;
;============================================================================
;
; sl_BlockSize-	Returns the size of the block pointed at by ES:DI.  If
;		ES:DI is not in the heap, then it returns zero.  Returns
;		the size, in bytes, in the CX register.

		public	sl_BlockSize
sl_BlockSize	proc	far
		assume	es:nothing, ds:nothing
		cmp	di, 8			;All ptrs have 8 as offset
		jne	BadBlkSize
		mov	cx, es
		cmp	cx, STDGRP:StartOfHeap
		jb	BadBlkSize
		cmp	cx, STDGRP:EndOfHeap
		jae	BadBlkSize
		mov	cx, esptr.BlkSize	;Get size of this block.
		ret

BadBlkSize:	xor	cx, cx
		ret
sl_BlockSize	endp



;============================================================================
;
; sl_MemAvail-	Returns the size of the largest free block available in
;		the heap.
;
; On Entry-	Nothing
; On Exit-	CX contains the size of the largest free block (in paras).

		public	sl_MemAvail
sl_MemAvail	proc	far
		assume	ds:nothing, es:nothing
		push	es
		push	ax
		xor	cx, cx			;Assume no free space.
		mov	ax, StdGrp:FreeSpace
		or	ax, ax
		je	MADone
FreeSpaceLp:	mov	ax, esptr.blksize
		cmp	ax, cx
		jb	NextFree
		mov	cx, ax
NextFree:	mov	es, esptr.FreeFwdPtr
		mov	ax, es
		or	ax, ax			;Quit when Fwd ptr is NIL.
		jnz	FreeSpaceLp

MADone:		pop	ax
		pop	es
		ret
sl_MemAvail	endp





;============================================================================
;
; sl_MemFree-	Returns the size of all the free blocks in the heap.
;
; On Entry-	Nothing
; On Exit-	CX contains the size of the free blocks (in paras).

		public	sl_MemFree
sl_MemFree	proc	far
		assume	ds:nothing, es:nothing
		push	es
		push	ax
		xor	cx, cx			;Assume no free space.
		mov	ax, StdGrp:FreeSpace
		or	ax, ax
		je	MFDone
FreeLp:		add	cx, esptr.blksize
		mov	ax, esptr.FreeFwdPtr
		mov	es, ax
		or	ax, ax
		jnz	FreeLp

MFDone:		pop	ax
		pop	es
		ret
sl_MemFree	endp






stdlib		ends
;
;
zzzzzzseg	segment	para public 'zzzzzz'
LastBytes	db	16 dup (?)
zzzzzzseg	ends
		end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -