Dynamically Offset Heap Clusters

Below is the code from the Kip Irvine compilation. I want to know what this code does. I understand that getProcessHeap returns a 32-bit integer handle to an existing program heap area in EAX. If the function should have completed, it will return a heap descriptor in EAX. If this fails, return value in EAX NULL

HeapAlloc allocates a block of memory from the heap. If successful, the return value in EAX contains the address of the memory block. If it fails, the return value in EAX is NULL.

How is the character distribution used in CALLOC?

How is integer allocation used in IALLOC?

Hoe is this long integer allocation used in LALLOC?

In MALLOC, how is the size in bytes allocated from the heap? Thanks to

INCLUDE Irvine32.inc 

HANDLE          TEXTEQU  <WORD> 

GetProcessHeap  PROTO 



HeapAlloc       PROTO, 
                hHeap : HANDLE, 
                dwflags: DWORD, 
                dwbytes: DWORD

HeapFree        PROTO, 
                hHeap : HANDLE,
                dwflags: DWORD,
                lpmem : DWORD 

.data 

hHeap HANDLE ? 

.code 

CALLOC          MACRO size  
                mov   eax, sizeof BYTE 
                imul  eax, size

                push  eax 
                call  MALLOC 
                ENDM 

IALLOC          MACRO size 
                mov   eax, sizeof WORD 
                imul  eax, size 

                push  eax 
                call  MALLOC 
                ENDM 

LALLOC          MACRO   size 
                mov     eax, sizeof DWORD 
                imul    eax, size 

                push    eax 
                call MALLOC 
                ENDM

MALLOC          PROC 
                push        ebp
                mov         ebp, esp 

                invoke      GetProcessHeap 
                invoke      HeapAlloc, eax, 8, [ebp + 8]

                pop     ebp 
                ret     4

MALLOC          ENDP 

MEMFREE         PROC 
                push    ebp 
                mov     ebp, esp 

                invoke  GetProcessHeap 
                invoke  HeapFree, eax, 0, [ebp + 8]

                pop     ebp 
                ret     4 
MEMFREE         ENDP

      

+3


source to share


1 answer


While your description of these functions is mostly correct, it is worth noting that GetProcessHeap

, HeapAlloc

and HeapFree

functions are actually Win32 API functions, which means they are provided as part of the operating system for application calls. The Irvine library has just provided prototypes for these functions to make them easier to call. So the semantics of these functions can be obtained directly from the horse's mouth by reading the Microsoft MSDN documentation (links above).

As the documentation explains, this is a common pattern for an application that needs to allocate a moderate amount of memory in order to simply get that memory from the process's default heap. This eliminates the need to create and the overhead of managing a separate personal heap, just for allocation. The functions HeapAlloc

and HeapFree

(and similarly named) are those that you should be using in modern Windows programming, not deprecated GlobalAlloc

or LocalAlloc

functions
that are sometimes still seen used or referenced in Windows programming material that have not been updated in this century.

Now, in the code you have, since everything eventually comes back to MALLOC

, start there. It sets up a stack frame, calls GetProcessHeap

, calls HeapAlloc

, and then pops the stack frame. You should see the error immediately. Remember in describing features GetProcessHeap

and HeapAlloc

you were careful to describe what happens if they fail? Well, you were right; these functions can fail, and properly written code must check for errors and handle them. This code doesn't work.

In MALLOC, how is the size in bytes allocated from the heap?

The implementation is MALLOC

pretty straightforward: all it really does is get a handle to the process heap and then use it HeapAlloc

to allocate memory from that heap. So if you want to know how it works, go back to the documentation forHeapAlloc

. From this we can see that the first parameter is the heap descriptor (returned from GetProcessHeap

to eax

), the second parameter is a bitwise combination of flags that control the allocation (in this case 8 or HEAP_ZERO_MEMORY

), and the third parameter is the number of bytes to allocate (in this case [ebp + 8]

) ...

[ebp + 8]

reads the first (and presumably only) parameter that was passed to the function MALLOC

on the stack. ( [ebp + 4]

is a pointer to the calling function (where MALLOC

would be ret

), and [ebp + 0]

is the original value ebp

stored when entering the function MALLOC

.)

In my opinion this is another (minor) bug with the function MALLOC

: it is not well documented! How are we supposed to know that it takes a parameter, and even more so the size / type and value of this parameter, without delving into its implementation? The main function and function interface should be documented right in the code using a comment.

So the answer to your question is, MALLOC

allocates as many bytes as you ask it to allocate.



How is the character distribution used in CALLOC?

This is a simple macro wrapped around a function MALLOC

. Its purpose is to determine how many bytes to allocate based on the number of characters you want to allocate for space, and then pass that value as a parameter MALLOC

.

The macro CALLOC

takes a single parameter size

, which is the number of characters for which you want to allocate space. (By the way, I think it size

is a bad choice of name for this parameter, since it is not very descriptive.)

It then multiplies the specified by the tag size

by the specified number of bytes required by the character, which is determined at build time by the expression sizeof BYTE

. This will give the number of bytes that really should be allocated. (Now, since it sizeof BYTE

is just 1, this is pretty stupid and inefficient code! I think it was written as "portable", but will come to assembly language!)

Finally, it pushes the result (the number of bytes allocated) onto the stack and calls MALLOC

to perform the allocation.

And now that you understand how it works CALLOC

, you should understand how all these macros work *ALLOC

, since they are all the same. IALLOC

multiplies its parameter by the size of the short integer ( sizeof WORD

) to get the actual number of bytes to allocate, and LALLOC

multiplies its parameter by the size of the long integer ( sizeof DWORD

).

(Note that while the multiplications in these other macros are necessary, they are also ineffective. sizeof WORD

== 2, so you can just shift left by 1. Or, better yet, add a value for yourself. sizeof DWORD

== 4, so left shift by 2. Additions and shifts are much faster than multiplications.)

+1


source







All Articles