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

 
Output of file : NEWSEG.ASM contained in archive : VCCRT1.ZIP
page ,132
title newseg - Get a new heap segment
;***
;newseg.asm - Get a new heap segment
;
; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
; Get a new segment and link it into the heap.
;
;*******************************************************************************

include version.inc
.xlist
include cmacros.inc
include msdos.inc
ifdef _WINDOWS
include rterr.inc
endif ;_WINDOWS
include heap.inc
.list

externNP _initseg ; initialize a heap segment
externNP _linkseg ; link a segment into the heap

ifdef _WINDOWS

extrn __amsg_exit:near ; write error and die
ifdef _BAT16
externP BatAllocSeg ; BAT16 allocate new segment
else
extrn GLOBALALLOC:far ; allocate new segment
endif ; _BAT16
extrn GLOBALLOCK:far ; lock down new segment
extrn GLOBALSIZE:far ; get size of segment

else ;!OS2 && !_WINDOWS



sBegin data
assumes ds,data

externW _aseghi ; highest segment so far
externW _aseglo ; smallest allowable segment

sEnd data

endif ; _WINDOWS


sBegin code
assumes cs,code
assumes es,data

ifdef _WINDOWS
extrn __wflags:word ; Windows status flags
endif

page
;***
;newseg - Get a new heap segment
;
;Purpose:
; Allocate a new segment and link it into the heap.
;
ifdef _WINDOWS
; Several different things to bear in mind for windows:
;
; Real mode = Get fixed memory
; Protect mode = Get moveable memory, then lock it
; Standard mode = Can't get exactly 64K due to a bug
endif
;
;Entry:
; cx = size of request
; es:di = dataoffset of heap linked list descriptor
; = unknown
;
;Exit:
; Success:
; carry = clear
; ds:bx = success = new heap descriptor
; Failure:
; carry = set
;
; cx = unchanged
;
;Uses:
; ax, dx, si
;
;Preserves:
; cx
;
;Exceptions:
;
;Note:
; The current method is to get a segment big enough to satisfy the
; caller's request, rounded up to the nearest paragraph, but not
; rounded up to the nearest multiple of _amblksize. This is the same
; behavior as in the 'old' heap. Subsequent requests will bring the
; segment size up to a multiple of _amblksize.
;
;*******************************************************************************


cProc _newseg,,<>

cBegin

;
; Calculate how big a segment we need
; cx = user's request size
;

mov dx,cx
ifdef _WINDOWS
add dx,_HEAP_MINSEG + (_HEAP_GROWSEG-1)
and dx,not (_HEAP_GROWSEG-1); dx = new segment size (rounded up
; to the nearest 4K boundary)
;validate our assumptions
.ERRE _HEAP_GROWSEG EQ 01000h

else
add dx,_HEAP_MINSEG + 0Fh
and dl,not 0Fh ; dx = new segment size (rounded up
; to the nearest paragraph)
endif

;
; Go get the segment
; cx = user's request size
ifdef _WINDOWS
; dx = new segment size (even 4K), 0 means 64K
else
; dx = new segment size (even paragraph), 0 means 64K
endif
;


ifdef _WINDOWS ; --- WINDOWS Segment Allocation

push cx ; preserve over system calls
push es

; need flags to detect real/standard/enhanced
mov bx,[__wflags] ; bx = windows flags word

; set up seg size paramter (cx:dx)
xor cx,cx ; # of segments = 0
or dx,dx ; is it 0 (i.e., 64K) ??
jnz @F ; nope, < 64K
; yes, 64K allocation
test bx,WF_STANDARD ; standard mode?
jnz error_rtn ; yes, error (can't get 64K in standard mode)
inc cx ; cx:dx = 64K
@@:

; allocate segment
; bx = __wflags, cx:dx = OS size request
push bx ; save __wflags around call
mov ax,_HEAP_PROTECT; assume protect mode
test bx,WF_PMODE ; protect mode ??
jnz @F ; jump if so
mov ax,_HEAP_REAL ; no, real mode
@@:
push ax ; flags
push cx ; # of full 64KB segments (hi word of long)
push dx ; # of bytes in final segment (low word)
ifdef _BAT16
call BatAllocSeg
add sp, 6
else
call GLOBALALLOC ; returns segment or 0 for error
endif ; _BAT16
pop bx ; bx = __wflags
or ax,ax ; error ??
jz error_rtn ; yes

;
; lock segment, if protect mode
;
; Protect mode assumption: call can never fail if
; GLOBALALLOC succeeds.
;

push ax ; save handle around subsequent calls

test bx,WF_PMODE ; protect mode ?
jz @F ; jump, if not

push ax ; push handle
call GLOBALLOCK ; lock down segment
or ax,ax ; make sure offset == 0
jnz fatal_err ; bogus
or ax,dx ; make sure pointer != 0
jz fatal_err ; bogus
mov ax,dx ; ax = new segment
@@:

assumes ds,nothing
mov ds,ax ; ds = new segment

; get seg size (windows may have rounded up)
push ax ; block handle
call GLOBALSIZE ; get block size
or dx,ax ; error ??
jz fatal_err ; ouch!!
mov dx,ax ; dx = block size (module 64k)

pop ax ; ax = handle
pop es ; restore registers
pop cx

else ; --- DOS Segment Allocation ---

mov bx,dx ; bx = new segment size
neg bx ; if bx = 0, set carry to
neg bx ; indicate 64K
cmc
rcr bx,1 ; pull in carry for 64K case
shr bx,1
shr bx,1
shr bx,1 ; bx = paragraph count

memcall:
callos allocmem ; get the new segment
jc done ; if carry, return error

; Perform segment checking/updating (for QC)
cmp ax,[_aseglo] ; new seg > _aseglo ??
jbe memcall ; no, try it again

cmp ax,[_aseghi] ; new seg > _aseghi ??
jbe set_ds ; nope, continue
mov [_aseghi],ax ; yes, update _aseghi
set_ds:
mov ds,ax ; ds = new segment
;fall thru

endif



;
; We have a new segment -- Initialize it.
ifdef _WINDOWS
; ax = handle of new segment
endif
; cx = size of request
; dx = size of segment
; ds = new segment selector
; es:di = dataoffset of heap list desc
;

xor bx,bx ; ds:bx = heap descriptor

ifdef _WINDOWS
mov [bx].handle,ax ; save handle of segment
endif
mov ax,es:[di].segflags ; ax = heap desc flags
mov [bx].flags,ax ; set heap descriptor flags

mov ax,dx ; ax = size of heap segment
call _initseg ; initialize the heap segment

;
; Link the new segment into the appropriate list.
; cx = size of request
; ds:bx = heap segment descriptor
; es:di = dataoffset of heap list desc
;

call _linkseg ; link new seg into [di] list
;fall thru

;
; --- Good return ---
;

clc ; clear carry for good return
jmp short done ; all done

ifdef _WINDOWS
;
; --- Fatal error ---
;

fatal_err:
mov ax,_RT_HEAP ; Unexpected heap error
jmp __amsg_exit ; fatal error handler

endif

;
; Error return
;

error_rtn:

ifdef _WINDOWS
pop es ; restore registers
pop cx
endif
stc ; carry set = error
;fall thru ; join common return

;
; Common return
;

done:
ret

cEnd

sEnd code

end


  3 Responses to “Category : C++ Source Code
Archive   : VCCRT1.ZIP
Filename : NEWSEG.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/