News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Heap Memory

Started by mabdelouahab, November 02, 2016, 05:56:25 PM

Previous topic - Next topic

mabdelouahab

how to managing Heap Memory without use api function

hutch--

With great difficulty and even if you can get it to work, Windows will probably break it with a future upgrade. If you use HeapAlloc() to get a main block, you can chop it up any way you like with a pointer array and data storage.

jj2007

StackBuffer:

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init      ; <<<< attention, this one is full of API calls
  mov ecx, 800000
  mov edi, StackBuffer(800000)
  mov al, "x"
  rep stosb
  StackBuffer()
  Inkey "easy..."
EndOfCode

nidud

#3
deleted

jj2007

If HEAPSIZE is above, say, 800000 as in my example, make sure you are not using the Microsoft assembler 8)

Besides, as Hutch already, there is not much to gain in rolling your own. The only reason would be if you have no access to the API - and that might be against the forum rules...

hutch--

You have not told us what the 800000 is yet. If you use /LARGEADDRESSAWARE with ML64 you can allocate over 32 gigabyte and I have so far tested 48 gigabyte. Are you trying to cripple ML64 with the assumptions of inferior tools ?  :biggrin:

hutch--

Here is an example of how to allocate large amounts of memory with ML64.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

entry_point proc

    LOCAL pMem :QWORD
    LOCAL pCnt :QWORD
    LOCAL pFre :QWORD

    heapinit                                ; initialise process heap

    mov pMem, halloc(1024*1024*1024*16)          ; allocate memory
    conout str$(pMem)," halloc",lf

    mov pCnt, hsize(pMem)                   ; display its size
    conout str$(pCnt)," hsize",lf

    mov pMem, hrealloc(pMem,1024*1024*1024*4)   ; reallocate memory
    conout str$(pMem)," hrealloc",lf

    mov pCnt, hsize(pMem)                   ; show new size
    conout str$(pCnt)," hsize",lf

    mov pFre, hfree(pMem)                   ; release allocated memory
    conout str$(pFre)," hfree",lf

    waitkey

    invoke ExitProcess,0

    ret

entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


With this result,

2189686345792 halloc
17179869184 hsize
2189686345792 hrealloc
4294967296 hsize
1 hfree
Press any key to continue...


ML64 may not be pretending to be a consumer friendly compiler but it clearly is powerful and that is because its a real assembler.  :biggrin:

jj2007

Hutch,
the 800000 is about the amount of bytes you can allocate with dup(?) without risking to need a coffee break. The bug is about twenty years old, and I just checked with ML64 - it's still there :greenclp:

hutch--

 :biggrin:

This is why its a feature, not a bug. Setting large allocations in the BBS section is appallingly bad code, why cater for lousy programming ?  :biggrin:

mabdelouahab

Thank you guys
Do I understand from your replys that I can exploit Bss Section Instead of using the Heap
QuoteThe heap area commonly begins at the end of the .bss and .data segments and grows to larger addresses from there
from:Data segment

mabdelouahab

From jj2007 on: January 07, 2012, 08:57:25 AM :biggrin:
Quote
Found this at http://www.tenouk.com/Bufferoverflowc/Bufferoverflow1c.html:
BSS stands for 'Block Started by Symbol'.  Global and statically allocated data that initialized to zero by default are kept in what is called the BSS area of the process.

Unfortunately it's for Linux BigGrin

Microsoft seems very shy to reveal its secrets, but I also remember that I once saw a MSDN or so reference. Probably it has to do with the fact that VirtualAlloc has no option for non-zeroed memory.

hutch--

The rough distinctions of memory fall into 3 categories, initialised data, uninitialised data that is set by the assembler at run time and dynamically allocated memory that is set by the programmer on demand. Dynamically allocated memory  can handle the very large allocations (gigabytes), unitialised memory has the advantage of being faster as it is pre-allocated at program start but comes at the price that it cannot have its size changed dynamically. Initialised data is usually used for string data but can have anything written to it as DB squences and then for some data, primarily resource data, you can place that data in the resource section. It can be either identified types of resources or raw binary.

RuiLoureiro

Hi
About this memory question, it seems that we are tallking about 3/4 types of memory allocation:

(1) - We allocate in the '.DATA?' segment (call it DATA? MEMMORY)

TOTALMEMORY     equ 800000
.DATA
pStartMemHereTypeI      dd offset StartMemHereTypeI     <--- pointer for type I
pStartMemHereTypeII     dd ?                            <--- pointer for type II
pStartMemHereTypeIII    dd ?                            <--- pointer for type III


.DATA?
StartMemHereTypeI  TOTALMEMORY dup (?)

(2) - We allocate using the API GlobalAlloc (call it GLOBAL MEMMORY)

            invoke  GlobalAlloc, TOTALMEMORY
            mov     pStartMemHereTypeII, eax

(3) - We allocate using the API HeapAlloc (call it HEAP MEMMORY)

            invoke  HeapAlloc, TOTALMEMORY
            mov     pStartMemHereTypeIII, eax

(4) - We allocate from the STACK (call it STACK MEMMORY)
      How to do it ?
      Why from Stack ?
      Is there any advantage ?
     
Another point of view: If we have a procedure that copies one block of memmory
to another, is there any type of timing advantage in this 4 cases ?
Is it faster if we use STACK MEMMORY ? Is it faster if we use DATA? MEMMORY ?
...

Jochen and Hutch, could you say something about this ?
Thanks
:icon14:

hutch--

Windows had had different memory strategies for a very long time, GlobalAlloc() with the GMEM_FIXED memory flag still works fine and it can handle very large allocations. You use the GMEM_MOVABLE for specific old style code like the clipboard. HeapAlloc() is the preferred modern method and if you stay away from the exotic but slow settings with it, it fast enough as well. VirtualAlloc() is mainly for large allocations that are not changed quickly.

Initialised memory is simple in assembler.

  .data
    mytext db "This is my text",0


Uninitialised memory is used to allocate space, mainly for variables, but without any specified content. It is used at run time by the programmer.

  .data?
    ptxt dw mytext  ; used as a pointer
    arr dd 16 dup (?)  ; 64 bytes