185 lines
4.1 KiB
NASM
185 lines
4.1 KiB
NASM
;_ sbrk.asm Thu Jul 13 1989 Modified by: Walter Bright */
|
||
; OS2 support added by Nikki Locke May 1989 */
|
||
; Copyright (C) 1985-1989 by Walter Bright
|
||
; All rights reserved
|
||
; Written by Walter Bright
|
||
|
||
include macros.asm
|
||
|
||
ifdef __OS2__
|
||
extrn DOSALLOCSEG:far
|
||
extrn DOSREALLOCSEG:far
|
||
endif
|
||
|
||
; Storage allocator
|
||
|
||
begdata
|
||
|
||
c_extrn errno,word
|
||
c_extrn _psp,word
|
||
c_extrn _datapar,word
|
||
c_extrn _pastdata,word
|
||
|
||
if SPTR
|
||
c_extrn _progpar,word
|
||
else
|
||
c_extrn _totalpar,word
|
||
endif
|
||
|
||
if LPTR
|
||
fardata dw 0
|
||
farsize dw 0
|
||
endif
|
||
|
||
enddata
|
||
|
||
begcode sbrk
|
||
|
||
c_public sbrk
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Request memory from operating system.
|
||
; Attempt to grow the data segment.
|
||
; Use:
|
||
; p = sbrk(nbytes);
|
||
; Returns:
|
||
; pointer to memory allocated
|
||
; (first word of allocated memory contains # of bytes allocated)
|
||
; -1 if error
|
||
|
||
func sbrk
|
||
push BP
|
||
mov BP,SP
|
||
mov BX,P[BP] ;get nbytes
|
||
add BX,15 ;round
|
||
and BX,0FFF0h ;BX = # of bytes to allocate
|
||
jnz sbr00
|
||
jmp sbrk3 ;error if sbrk(0)
|
||
sbr00: mov DX,BX ;save
|
||
mov CL,4
|
||
shr BX,CL ;# of paragraphs to allocate
|
||
mov CX,BX ;save
|
||
ifdef __OS2__
|
||
mov P[BP],DX ;save no of bytes to allocate
|
||
add BX,_datapar ;add in # already in data segment
|
||
jc sbradd ;more than 64k
|
||
.if BX a 0FFFH, sbradd ;more than 64k
|
||
push CX ;save no of paras to add
|
||
mov CL,4
|
||
shl BX,CL ;no of bytes
|
||
push BX ;new size requested
|
||
push DS ;current data segment
|
||
call DOSREALLOCSEG
|
||
pop CX ;restore no of paras added
|
||
test AX,AX
|
||
jnz sbradd ;cannot add to this segment
|
||
mov DX,P[BP] ;no of bytes allocated
|
||
mov AX,_pastdata ;pointer to allocated memory
|
||
mov BX,AX
|
||
mov [BX],DX ;store # of bytes allocated
|
||
add _pastdata,DX ;and remember for posterity
|
||
add _datapar,CX ;new size of data segment
|
||
if LPTR
|
||
mov DX,DS ;segment selector
|
||
endif
|
||
jmp short sbrkok ;ok return
|
||
|
||
sbradd:
|
||
if SPTR
|
||
jmp short sbrk3
|
||
else
|
||
mov AX,fardata
|
||
test AX,AX
|
||
jz sbrnew ;allocate a new segment
|
||
mov BX,farsize
|
||
add BX,P[BP] ;add requested size
|
||
jc sbrnew ;>=64k
|
||
push BX ;save size
|
||
push BX ;new size requested
|
||
push AX ;far data segment
|
||
call DOSREALLOCSEG
|
||
pop BX ;get back size
|
||
test AX,AX
|
||
jnz sbrnew ;cannot add to this segment
|
||
mov AX,farsize ;offset to new memory
|
||
|
||
jmp short sbrlok
|
||
|
||
sbrnew: mov BX,P[BP]
|
||
push BX
|
||
push DS
|
||
push offset DGROUP:fardata ;address of where to put segment
|
||
push 0 ;flag as non-shareable
|
||
call DOSALLOCSEG
|
||
test AX,AX
|
||
jnz sbrk2
|
||
xor AX,AX ;offset = 0 for new segment
|
||
mov BX,P[BP] ;no of bytes allocated
|
||
sbrlok:
|
||
mov CX,P[BP] ;no of bytes allocated
|
||
mov DX,fardata ;segment of memory block
|
||
mov farsize,BX ;replace old size with new
|
||
mov BX,AX
|
||
mov ES,DX
|
||
mov ES:[BX],CX ;store # of bytes allocated
|
||
endif
|
||
sbrkok:
|
||
else ;__OS2__
|
||
if SPTR
|
||
add BX,_datapar ;add in # already in data segment
|
||
jc sbrk3 ;too much
|
||
.if BX a 0FFFh, sbrk3 ;if > 64k
|
||
add BX,_progpar ;BX = total new size of program
|
||
else
|
||
add BX,_totalpar ;BX = total new size of program
|
||
endif
|
||
push ES
|
||
mov ES,_psp ;segment of start of program
|
||
bdos 4Ah ;set new program size
|
||
pop ES
|
||
|
||
if SPTR
|
||
jc sbrk2 ;failed
|
||
mov AX,_pastdata ;pointer to allocated memory
|
||
mov BX,AX
|
||
mov [BX],DX ;store # of bytes allocated
|
||
add _pastdata,DX ;and remember for posterity
|
||
add _datapar,CX ;new size of data segment
|
||
else
|
||
jnc sbrkok ;succeeded
|
||
.if AX ne 8, sbrk2 ;if something is very wrong
|
||
|
||
;Can't grow data segment. Try to allocate an independent block.
|
||
; sub BX,_totalpar ;BX = # of paragraphs req'd
|
||
mov BX,CX ;BX = # of paragraphs req'd
|
||
bdos 48h ;allocate memory
|
||
jc sbrk2 ;failed
|
||
jmps sbrk1 ;success. AX = segment of new block
|
||
sbrkok:
|
||
mov AX,_psp
|
||
add AX,_totalpar ;AX = segment of new block
|
||
add _totalpar,CX ;new total size of program
|
||
sbrk1:
|
||
clr BX ;BX = offset of new block
|
||
mov ES,AX
|
||
mov ES:[BX],DX ;store size of new block
|
||
mov DX,AX
|
||
mov AX,BX
|
||
endif
|
||
endif ;__OS2__
|
||
pop BP
|
||
ret
|
||
|
||
sbrk3: mov AX,8 ;fake an ENOMEM
|
||
sbrk2: mov errno,AX
|
||
mov AX,-1
|
||
if LPTR
|
||
cwd
|
||
endif
|
||
pop BP
|
||
ret
|
||
c_endp sbrk
|
||
|
||
endcode sbrk
|
||
end
|
||
|