EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

memory64.htm
Classes
BUFFER
Macros
BufferClear
BufferCreate
BufferDestroy
BufferRetrieve
BufferStore

This file contains OS-independent macroinstructions for dynamic memory management in 64bit programs written in Euro Assembler.
It requires that the program which includes this file "memory64.htm" also included either "winabi.htm" or "linabi.htm".

All macros in this library return carry flag set if some error occurs, which usually signalizes lack of system memory or bad parameter. Returned values are not valid when CF=1.


memory64 HEAD ; Library interface.
↑ BUFFER

Object BUFFER is an unformated storage for objects (strings) of arbitrary size.

Items with fixed or variable size can be stored to the buffer one after another and the entire buffer content is always available as a continuous block.

The initial Size specified at the BUFFER creation should be large enough to accomodate all expected data. Whenever the total buffer size tries to exceed the allocated size specified at buffer creation, data area is reallocated with doubled size, the old buffer contents is copied to the new position and the original buffer space is abandoned.

enlarged twice ┌ ╔════════╗ <─┐ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ free ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ ║<┐ │ enlarged │ ║░░░░░░░░║ │ │ once │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ ┌ ╔════════╗ <─┐ ┌ ╔════════╗ <─┐ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║ ║<┐ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ free ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ created │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║<┐ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ ┌ ╔════════╗<──┐ ┌ ╔════════╗<──┐ │ ║░░░░░░░░║ │ │ ┌ ╔════════╗<──┐ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║ ║<┐ │ │ ║░░░░░░░░║ │ │ │ ║ ║<┐ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ free ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║ ║<┐ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ 64KB│ ║░░░░░░░░║ │ │ 64KB│ ║░wasted░║ │ │ 128KB│ ║░░░░░░░░║ │ │ 64KB│ ║░wasted░║ │ │ 128KB│ ║░wasted░║ │ │ 256KB│ ║░░░░░░░░║ │ │ │ ║░payload║ │ │ │ ║░payload║ │ │ │ ║░payload║ │ │ │ ║░payload║ │ │ │ ║░payload║ │ │ │ ║░payload║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ║░░░░░░░░║ │ │ │ ╟────────╢ │ │ │ ╟────────╢ │ │ │ ╟────────╢ │ │ │ ╟────────╢ │ │ │ ╟────────╢ │ │ │ ╟────────╢ │ │ │ ║.Ptr ╟─┘ │ │ ║.Ptr ╟─┘ │ │ ║.Ptr ╟─┘ │ │ ║.Ptr ╟─┘ │ │ ║.Ptr ╟─┘ │ │ ║.Ptr ╟─┘ │ │ ╟────────╢ │ │ ╟────────╢ │ │ ╟────────╢ │ │ ╟────────╢ │ │ ╟────────╢ │ │ ╟────────╢ │ │ ║.Top ╟───┘ │ ║.Top ╟───┘ │ ║.Top ╟───┘ │ ║.Top ╟───┘ │ ║.Top ╟───┘ │ ║.Top ╟───┘ │ ╟────────╢ │ ╟────────╢ │ ╟────────╢ │ ╟────────╢ │ ╟────────╢ │ ╟────────╢ │ ║.Prev=0 ║ │ ║.Prev=0 ║ │ ║.Prev ╟──────┐ │ ║.Prev=0 ║ │ ║.Prev ╟──────┐ │ ║.Prev ╟──────┐ │ ╟────────╢ │ ╟────────╢ │ ╟────────╢ │ │ ╟────────╢ │ ╟────────╢ │ │ ╟────────╢ │ │ ║.Last=0 ║ │ ║.Last ╟─────────┐ │ ║.Last=0 ║ │ │ ║.Last ╟─────────┐ │ ║.Last ║ │ │ ║.Last=0 ║ │ └ ╚════════╝<──┐ └ ╚════════╝<──┐ <┐ │ └ ╚════════╝<──┐ │ └ ╚════════╝<──┐ <┐ │ └ ╚════════╝ <────│──┐ └ ╚════════╝<──┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ aBuffer──────┘ aBuffer──────┘ │ └─────────────────────┘ │ aBuffer──────┘ │ └────────────────────────│──│──────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────┘ └───────────────────────────┘ └─────────────────────────┘
BUFFER STRUC
.Last   D QWORD ; Ptr to the last, active block. 0 if the current block is active. Other blocks are unused.
.Prev   D QWORD ; Ptr to the previous memory block, or 0 if none. Used in BufferDestroy.
.Top:   D QWORD ; Ptr to the top of this block (end of the allocated buffer space).
.Ptr:   D QWORD ; Ptr to the next free space in the buffer.
     ENDSTRUC BUFFER
↑ BufferCreate Size=64K
will allocate an empty (cleared) buffer from OS virtual memory.
Input
Size= is the initial size of the entire BUFFER plus payload data. It will be rounded up to the fixed granularity 64 KB.
When underestimated, it will be automatically increased if necessary but this wastes memory.
Output
CF=0, RAX=pointer to the BUFFER (buffer handle).
Error
CF=1, RAX=0 or error number when allocation error occured.
Depends on
macro MemAlloc defined in winabi.htm or linabi.htm.
BufferCreate %MACRO Size=64K
     MOV RAX,%Size
     CALL BufferCreate@RT
BufferCreate@RT:PROC1
     PUSH RBX,RCX
      MOV RBX,RAX
      ADD RBX,64K-1
      AND RBX,-64K
      MemAlloc RBX  ; Macro defined in winabi.htm or linabi.htm.
      JC .90:
      LEA RCX,[RAX+RBX]
      MOV [RAX+BUFFER.Top],RCX
      LEA RCX,[RAX+SIZE#BUFFER]
      MOV [RAX+BUFFER.Ptr],RCX
.90: POP RCX,RBX
     RET
    ENDP1 BufferCreate@RT
   %ENDMACRO BufferCreate
↑ BufferDestroy aBuffer, aBuffer2, aBuffer3,,,
will free the buffer, i. e. unallocate memory currently stored in the buffer and its predecessors, if any.
Input
aBuffer is a pointer to the BUFFER structure which was returned from BufferCreate . It may be NULL.
Output
-
Error
-
BufferDestroy %MACRO aBuffer, aBuffer2,,,
     PUSH RCX
      %WHILE "%1" !=== ""
       MOV RCX,%1
       JRCXZ BufferDestroy%.:
       CALL BufferDestroy@RT
BufferDestroy%.:
       %SHIFT 1
      %ENDWHILE
     POP RCX
BufferDestroy@RT: PROC1      ; RCX=^BUFFER.
     PUSH RAX,RCX
      PUSHQ [RCX+BUFFER.Prev]
       MemFree RCX          ; Macro defined in winabi.htm or linabi.htm.
      POP RCX
      JRCXZ .90:             ; Skip when there was no previous buffer.
      CALL BufferDestroy@RT: ; Otherwise destroy the previous buffers recursively.
.90: POP RCX,RAX
     RET
    ENDP1 BufferDestroy@RT:
   %ENDMACRO BufferDestroy
↑ BufferStore aBuffer, DataPtr, DataSize
will copy DataSize bytes of the data specified with DataPtr on the buffer.
Input
aBuffer is a pointer to a BUFFER structure which was returned from BufferCreate.
DataPtr is a pointer to data to be stored on the buffer.
DataSize is the requested data size in bytes.
Output
CF=0, data were stored to the buffer.
Error
CF=1 on allocation error or not created buffer.
Depends on
BufferCreate
BufferStore %MACRO aBuffer, DataPtr, DataSize
     PUSHQ %DataSize, %DataPtr, %aBuffer
     CALL BufferStore@RT::
BufferStore@RT:PROC1
      PUSH RAX,RBX,RCX,RSI,RDI
       MOV RBX,[RSP+6*8]     ; aBuffer
       TEST RBX
       STC
       JZ .90:
       MOV RCX,[RBX+BUFFER.Last]
       JRCXZ .20:
       MOV RBX,RCX
.20:   MOV RSI,[RSP+7*8]               ; DataPtr
       MOV RCX,[RSP+8*8]               ; DataSize
       MOV RAX,[RBX+BUFFER.Top]
       MOV RDI,[RBX+BUFFER.Ptr]
       SUB RAX,RDI                     ; Available memory remaining in the buffer.
       CMP RCX,RAX
       JBE .70:                        ; Jump when DataSize is lower.
       PUSH RDX,RDI                    ; Old buffer is not large enough.
         MOV RAX,[RBX+BUFFER.Top]
         PUSH RAX
           SUB RAX,RBX
           ADD RAX,RAX                 ; Double the buffer size
           ADD RAX,RCX                 ;  and add the DataSize for a good measure.
           CALL BufferCreate@RT:       ; Create the new buffer with size=RAX.
         POP RCX                       ; RBX is the old buffer, RCX its .Top, RAX is the new buffer.
         JC .60:                       ; CF when allocation error ocurred.
         MOV RSI,RBX                   ; RSI=Old buffer.
         MOV RDI,RAX                   ; RDI=New buffer.
         SUB RCX,RBX                   ; RCX=size of the old buffer.
         MOV RDX,[RAX+BUFFER.Top]      ; Temporarily backup the new buffer's .Top.
         SHR RCX,3                     ; Size in QWORDs.
         REP MOVSQ                     ; Copy the entire old buffer including its contents.
         MOV RCX,[RBX+BUFFER.Ptr]      ; Convert old buffer's .Ptr to the new one.
         SUB RCX,RBX
         ADD RCX,RAX
         MOV [RAX+BUFFER.Top],RDX      ; Restore new buffer's .Top.
         MOV [RAX+BUFFER.Ptr],RCX      ; Update new buffer's .Ptr.
         MOV [RAX+BUFFER.Prev],RBX
         MOV [RAX+BUFFER.Last],0
         MOV [RBX+BUFFER.Last],RAX
         MOV RCX,[RBX+BUFFER.Prev]
.40:     JRCXZ .50:
         MOV [RCX+BUFFER.Last],RAX
         MOV RCX,[RCX+BUFFER.Prev]
         JMP .40:
.50:     MOV RBX,RAX
         CLC
.60:   POP RDI,RDX
       JC .90:
       JMP .20:
.70:   REP MOVSB
       MOV [RBX+BUFFER.Ptr],RDI
       CLC
.90:  POP RDI,RSI,RCX,RBX,RAX
      RET 3*8
     ENDP1 BufferStore@RT:
    %ENDMACRO BufferStore
↑ BufferRetrieve aBuffer
will return pointer and size of all data currently stored in the buffer.
Input
aBuffer is a pointer to the BUFFER structure which was returned from BufferCreate . Macro returns RCX=RSI=0,CF=1 when aBuffer is NULL.
Output
CF=0
RSI=Pointer to the stored data (aBuffer+SIZE#BUFFER).
RCX=Size of the stored data (aBuffer.Ptr - (aBuffer+SIZE#BUFFER))
ZF=1 when RCX=0 (buffer exists and it is empty), otherwise ZF=0.
Error
CF=1,RCX=RSI=0 (uncreated buffer)
Example
BufferRetrieve RBX ; RBX is pointer to a buffer, or 0. JNA .NoData: ; Jump when the buffer is empty (RCX=0,ZF=1) or hasn't been created (CF=1).
BufferRetrieve %MACRO aBuffer
    PUSHQ %aBuffer
    CALL BufferRetrieve@RT:
BufferRetrieve@RT: PROC1
    MOV RCX,[RSP+8]
    MOV RSI,RCX
    STC
    JRCXZ .90:
    MOV RCX,[RSI+BUFFER.Last]
    JRCXZ .50:
    MOV RSI,RCX
.50:MOV RCX,[RSI+BUFFER.Ptr]
    LEA RSI,[RSI+SIZE# BUFFER]
    SUB RCX,RSI
.90:RET 8
   ENDP1 BufferRetrieve@RT:
 %ENDMACRO BufferRetrieve
↑ BufferClear aBuffer
will reset the buffer contents but does not free the allocated space.
Input
aBuffer is a pointer to the BUFFER structure which was returned from BufferCreate . Macro returns CF=1 when aBuffer is NULL.
Output
CF=0
Error
CF=1 (uncreated buffer)
BufferClear %MACRO aBuffer
    PUSH RAX,RCX
      MOV RCX,%aBuffer
      STC
      JRCXZ BufferClearE%.:
      MOV RAX,RCX
      MOV RCX,[RAX+BUFFER.Last]
      JRCXZ BufferClearD%.:
      MOV RAX,RCX
BufferClearD%.:
      LEA RCX,[RAX+SIZE# BUFFER]
      MOV [RAX+BUFFER.Ptr],RCX
      CLC
BufferClearE%.:
    POP RCX,RAX
 %ENDMACRO BufferClear
 ENDHEAD memory64 ; End of the library interface.

▲Back to the top▲