home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / CLIBSRC3.ZIP / ALLOCA.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-06-10  |  5.4 KB  |  161 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      ALLOCA.ASM -- Allocate temporary stack space                 |
  3. ;[]-----------------------------------------------------------------[]
  4.  
  5. ;
  6. ;       C/C++ Run Time Library - Version 5.0
  7. ;       Copyright (c) 1991, 1992 by Borland International
  8. ;       All Rights Reserved.
  9.  
  10.         INCLUDE RULES.ASI
  11.  
  12. ;       Segments Definitions
  13.  
  14. Header@
  15.  
  16. ;----------------------------------------------------------------------
  17. ; In large data models, the stack is in its own segment.  The stack
  18. ; starts at SS:__stklen and grows down to SS:0.
  19. ;
  20. ; In small data models, the stack is in the DGROUP, and grows down
  21. ; to meet the heap.  The end of the heap is marked by ___brklvl.
  22. ;----------------------------------------------------------------------
  23.  
  24. ifdef _WINDOWS
  25. pStackTop equ   0Ah             ; SS:[0A] contains addr of top of stack
  26. else
  27.   if LDATA eq false
  28. ExtSym@         __brklvl, WORD, __CDECL__
  29.   endif
  30. endif
  31.  
  32. ; REGSTACK contains the number of bytes taken up in the stack
  33. ; by registers saved in the normal function prologue.  This includes
  34. ; space for SI and DI, plus DS in huge model.
  35.  
  36. ifdef __HUGE__
  37. REGSTACK   equ     6
  38. else
  39. REGSTACK   equ     4
  40. endif
  41.  
  42. ;----------------------------------------------------------------------
  43. ; Name          alloca - allocate temporary stack memory
  44. ;
  45. ; Usage         void *alloca(size_t size);
  46. ;
  47. ; Prototype in  malloc.h
  48. ;
  49. ; Description   Alloca allocates size bytes on the stack; the allocated
  50. ;               space is automatically freed up when the calling function
  51. ;               exits.
  52. ;
  53. ;               Because alloca modifies the stack pointer, do not place calls
  54. ;               to alloca in an expression that is an argument to a function.
  55. ;
  56. ;               If the calling function does not contain any references
  57. ;               to local variables in the stack, the stack will not
  58. ;               be restored correctly when the function exits, resulting
  59. ;               in a program crash.  To ensure that the stack is restored
  60. ;               correctly, use the following code in the calling function:
  61. ;
  62. ;                       char *p;
  63. ;                       char dummy[1];
  64. ;
  65. ;                       dummy[0] = 0;
  66. ;                       ...
  67. ;                       p = alloca(nbytes);
  68. ;
  69. ; Return value  Returns a pointer to the allocated stack area on success.
  70. ;               If the stack cannot be extended, a NULL pointer is returned.
  71. ;               The returned pointer should never be passed to free().
  72. ;
  73. ; Note          Compatible with Microsoft C and UNIX.  Not recommended.
  74. ;               Use malloc() instead.
  75. ;----------------------------------------------------------------------
  76.  
  77. Code_seg@
  78.  
  79. PubProc@ alloca, __CDECL__
  80.  
  81.         pop     bx              ; pop return address (offset)
  82. if LPROG
  83.         pop     es              ; pop return address (segment)
  84. endif
  85.         pop     ax              ; pop size parameter
  86.         add     ax,1            ; round size up to even number of bytes
  87.         and     ax,not 1
  88.         neg     ax              ; negate size
  89.         add     ax,sp           ; add current stack pointer
  90.  
  91. ; Put into cx the value sp would attain after adding the space
  92. ; for pushing the return address and size parameter, and copies
  93. ; of the register variables saved in the caller's stack.  Compare
  94. ; this value with the stack base to guard against stack overflow.
  95.  
  96.         mov     cx,ax           ; add some extra to ensure there's room for
  97.         sub     cx,REGSTACK+cPtrSize+2   ; ret address, size, and regs
  98.         cmp     cx,sp           ; would new SP wrap around?
  99.         ja      bad
  100. ifdef _WINDOWS
  101.         cmp     ss:pStackTop,cx ; would new SP go below top of stack?
  102.         ja      bad
  103. else
  104.     if LDATA eq false
  105.         cmp     __brklvl@,cx    ; would new SP fall in the near heap?
  106.         ja      bad
  107.     endif
  108. endif
  109.         mov     cx,bp           ; save BP in CX
  110.         mov     bp,sp           ; get a copy of SP into BP for later use
  111.  
  112. ; The current stack looks like this, from high to low address:
  113. ;       SI saved by caller (assumed to be present)
  114. ;       DI saved by caller (assumed to be present)
  115. ; BP -> DS saved by caller (present only in huge model)
  116. ;       ... empty space ...
  117. ; AX -> new stack area
  118. ;
  119. ; Before we can return, we need to push on the new stack area the registers
  120. ; saved by caller in the old stack area.  We need to copy at least 2 stack words
  121. ; (for SI and DI), plus one more in huge model (DS).  We can't tell if SI
  122. ; and DI were really saved, so we assume that they were and allocate extra
  123. ; space for them.
  124.  
  125.         mov     sp,ax           ; set up new SP
  126. ifdef __HUGE__
  127.         push    [bp+4]
  128. endif
  129.         push    [bp+2]
  130.         push    [bp+0]
  131. if LDATA
  132.         mov     dx,ss           ; return high word of stack address in DX
  133. endif
  134.         mov     bp,cx           ; restore caller's BP
  135. return:
  136.         sub     sp,2            ; caller will add 2 to SP after we return
  137. if LPROG
  138.         push    es              ; can't "jmp es:bx", so push es:bx,
  139.         push    bx              ;  then do a far return
  140.         retf
  141. else
  142.         jmp     bx              ; return
  143. endif
  144.  
  145. ; Come here if there isn't enough stack space.  Return a null pointer.
  146.  
  147. bad:
  148.         xor     ax,ax           ; return NULL pointer
  149. if LDATA
  150.         mov     dx,ax
  151. endif
  152.         jmp     return
  153.  
  154. EndProc@ alloca, __CDECL__
  155.  
  156. Code_EndS@
  157.  
  158.         end
  159.