alloca() for TurboC
Dale Smith
dale at NCoast.ORG
Thu Aug 23 13:27:51 AEST 1990
In article <1990Aug22.032243.18214 at usenet.ins.cwru.edu> trier at po.CWRU.Edu writes:
>Here's a version of alloca I use. It's my clone of a version from some
>piece of PD software I saw a year or two ago.
>
> #define alloca(A) ((_SP -= ((A)+1) & 0xFFFE), (void far *)(((unsigned long)_SS << 16) | _SP))
>
>The idea is to subtract the size A from the stack pointer, making sure
>it's word-aligned. (This is the (_SP -= ((A)+1) & 0xFFFE) part.) Then,
>since alloca returns a pointer to the allocated space, the macro must
>kludge together a far pointer from the stack segment and stack pointer.
>
>I should add the disclaimer that I'm not entirely sure that this works.
>It's my own version of someone else's, but I changed it a bit. (I don't
>remember what the original looked like.)
>
>Hope this helps!
>
>--
>Stephen Trier Case Western Reserve University
>Home: sct at seldon.clv.oh.us Information Network Services
>Work: trier at cwlim.ins.cwru.edu
> I may work for the University, but that doesn't mean I speak for them.
I believe I saw something like that in an early port of bison. It's
really cute but will trash register variables.
Someone posted an alloca for the 386 which I hacked to fit Turbo C.
I also took a peek at a disassembly of the Microsoft C 5.1 alloca().
Here it is, have fun.
------ Snip it or somethin' ------------------------------
; alloca.asm
; Allocate from the stack for Turbo C 2.0
; I have not tried this this TC++ 1.0
; void *alloca(size_t size);
; Beware of using alloca in functions without arguments
; and -k- in tiny, small, and medium models. The stack has a
; possibility of growing.
ifdef __TINY__
.model tiny
elseifdef __SMALL__
.model small
elseifdef __MEDIUM__
.model medium
elseifdef __COMPACT__
.model compact
elseifdef __LARGE__
.model large
elseifdef __HUGE__
.model huge
else
.model small
endif
if @DataSize EQ 0
.data
extrn ___brklvl:word
endif
.code
public _alloca
_alloca proc
;; Pop return address into (es:) cx and size into ax
pop cx ; return address
if @CodeSize
pop es ; return segment
endif
pop ax ; size
;; Make sure that ax is greater than zero, and is a multiple of two.
cmp ax,0
jl error
inc ax
and ax,not 1
;; Figure new stack pointer, check for negative and less than brk.
mov bx,sp
sub bx,ax
jb error ; below zero
if @DataSize EQ 0 ; tiny, small, medium
cmp bx,___brklvl
jb error ; below the brk
endif
xchg sp,bx
mov ax,sp
;; Copy the (hypothetical) register variables.
ifdef __MEDIUM__
push ss:6[bx] ; return segment(medium)
endif
push ss:4[bx] ; return offset(med,sm,tiny) or ds(huge)
push ss:2[bx] ; di (all)
push ss:[bx] ; si (all)
if @DataSize
mov dx,ss
endif
exit:
;; Put something on the stack so that our caller can pop it off.
push ax
;; Return to the the caller.
if @CodeSize
push es
push cx
ret
else
jmp cx
endif
error:
xor ax,ax
if @DataSize
cwd
endif
jmp exit
endp
end
-------------- Ok, that's it -----------------------------------------
dale
--
Dale P. Smith
dale at ncoast.org
uunet!usenet.ins.cwru.edu!ncoast!dale
More information about the Comp.lang.c
mailing list