Category : C++ Source Code
Archive   : VCCRT1.ZIP
Filename : UNLINKSG.ASM

 
Output of file : UNLINKSG.ASM contained in archive : VCCRT1.ZIP
page ,132
title unlinksg - Unlink and free a heap segment
;***
;unlinksg - Unlink and free a heap segment
;
; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
; Contains the _unlinkseg() routine that unlinks and frees the supplied
; heap segment.
;
;*******************************************************************************

.xlist
include version.inc
include cmacros.inc
include msdos.inc
include heap.inc
.list

ifdef _WINDOWS
ifdef _BAT16
externP BatFreeSeg ; BAT16 free global memory
else
extrn GLOBALFREE:far ; WIN free global memory
endif
extrn GLOBALUNLOCK:far ; WIN unlock global memory
endif



sBegin code
assumes cs,code
assumes ds,nothing

ifdef _WINDOWS
extrn __wflags:word ; Windows status flags
endif

page
;***
;_unlinkseg - Unlink and free a heap segment.
;
;Purpose:
; Unlink a heap segment and free it (i.e., release it back to the OS).
; This routine first unlinks the segment from the heap segment list
; and updates the heap list descriptor (if necessary). Then, it frees
; the segment.
;
;Entry:
; ds:bx = pointer to the heap segment descriptor
; es:di = pointer to heap list descriptor
;
;Exit:
; ds:bx = pointer to heap list descriptor
; cf = 0 (clear), if segment was freed back to the OS
; = 1 (set), if OS call to free the segment returned an error
;
;Uses:
; ax, bx, cx, dx, si, di, ds, es
;
;Preserves:
; nothing
;
;Exceptions:
;
;*******************************************************************************

cProc _unlinkseg,,<>

cBegin

; Fetch the prevseg and nextseg pointers from the heap segment descriptor,
; and set ds:bx to point to the heap list descriptor.
;
; Exit: (fall thru only)
; ds:bx = pointer to heap list descriptor
; dx:si = prevseg
; es:di = nextseg
; ax = es
; TOS = selector for the heap segment
ifdef _WINDOWS
; TOS+2 = handle for heap segment
endif

ifdef _WINDOWS
mov ax,[bx].handle ; save segment handle on stack
push ax
endif


push es ; save pointer to heap list desc. on
push di ; stack
les si,[bx].prevseg ; es:si = pointer to heap seg desc of
; previous heap segment
mov dx,es ; dx = segment(prevseg)
les di,[bx].nextseg ; es:di = pointer to heap seg desc of
; the next heap segment
mov ax,es ; ax = segment(nextseg)
mov cx,ds ; temporarily save selector in cx
pop bx
pop ds ; ds:bx = pointer to heap list desc.
push cx ; save heap seg selector on stack

; Check nextseg, the forward link. If it's NULL, update the lastseg field
; of the heap list descriptor with prevseg. Otherwise, update
; [nextseg].prevseg (with prevseg).
;
; Entry:
; ds:bx = heap list descriptor
; es:di = nextseg
; dx:si = prevseg
; ax = es
;
; Exit Paths:
; chk_prevseg
;
; Uses:
; ax

or ax,di ; nextseg = NULL?
jnz not_lastseg ; no, go update [nextseg].prevseg
mov word ptr ds:[bx].lastseg,si ; update lastseg field
mov word ptr ds:[bx].lastseg+2,dx
jmp short chk_prevseg


; bad_freeseg

; *** SHOULD ERRNO BE SET TO E_?????? ****

bad_freeseg:
stc ; set carry flag to indicate error
jmp short done

not_lastseg:
mov word ptr es:[di].prevseg,si ; [nextseg].prevseg = prevseg
mov word ptr es:[di].prevseg+2,dx

; Check prevseg, the backward link. If it's NULL, update the startseg field
; of the heap list descriptor. Otherwise, update [prevseg].nextseg (with
; nextseg).
;
; Entry:
; ds:bx = heap list descriptor
; es:di = nextseg
; dx:si = prevseg
;
; Exit Paths:
; chk_roverseg
;
; Uses:
; ax, dx, es

chk_prevseg:
mov ax,es ; ax:di = nextseg
mov es,dx ; es:si = dx:si = prevseg
or dx,si ; prevseg = NULL?
jz firstseg ; yes, go update startseg field
mov word ptr es:[si].nextseg,di ; [prevseg].nextseg = nextseg
mov word ptr es:[si].nextseg+2,ax
jmp short chk_roverseg
firstseg:
mov word ptr ds:[bx].startseg,di ; update startseg field
mov word ptr ds:[bx].startseg+2,ax

; chk_roverseg
; Check to see if the heap segment is the rover segment. If so, set the
; roverseg field of the heap list descriptor to startseg.
;
; Entry:
; ds:bx = heap list descriptor
; TOS = selector for the heap segment
;
; Exit Paths:
; free_seg
;
; Uses:
; ax, dx

chk_roverseg:
pop ax ; pop selector for heap segment
push ax ; also keep on TOS for later use
cmp ax,word ptr ds:[bx].roverseg+2 ; is it the same as the rover seg?
jne free_seg ; no, no need to update it
mov dx,word ptr ds:[bx].startseg ; reset _fheap_rover to be _fheap_start
mov word ptr ds:[bx].roverseg,dx
mov dx,word ptr ds:[bx].startseg+2
mov word ptr ds:[bx].roverseg+2,dx

; free_seg
; Free the segment back to the OS.
;
; Entry:
; TOS = selector for the heap segment
ifdef _WINDOWS
; TOS+2 = handle for heap segment
endif
;
; Exit Paths:
; bad_freeseg (OS call failed)
; done (OS call successful)

free_seg:


ifdef _WINDOWS ; --- WINDOWS Segment Free ---

pop ax ; pop off selector, don't need it
; TOS now equals handle

; unlock block, if protect mode
test [__wflags],WF_PMODE ; Are we in protect mode ??
jz @F ; jump if not
pop ax ; ax = handle
push ax ; once for GLOBALLOCK
push ax ; once for GLOBALFREE
call GLOBALUNLOCK ; unlock the segment
@@:
; free block ; handle already on stack
ifdef _BAT16
call BatFreeSeg
else
call GLOBALFREE ; free segment
endif ; _BAT16P
or ax,ax ; error ??
jnz bad_freeseg ; (note side effect: cf is cleared)

else ; --- DOS Segment Free ---

pop es ; pop heap seg selector into es
callos freemem ; free segment
jc bad_freeseg
endif


; fall thru (note carry flag is clear)

done:
ret

cEnd

sEnd code
end


  3 Responses to “Category : C++ Source Code
Archive   : VCCRT1.ZIP
Filename : UNLINKSG.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/