The following is a code provided in the Assembly Kip Irvine book. I want to know what this code is doing. I understand that the getProcessHeap returns a 32 bit integer handle to the program's existing heap area in EAX. If the function were to suceed, it will return a handle to the heap in EAX. If it fails, the return value in EAX is NULL
The HeapAlloc allocates a block of memory from a heap. If it succeeds, the return value in EAX contains the address of memory block. If it fails, the returned value in EAX is NULL.
How is character allocation being used in CALLOC?
How is integer allocation being used in IALLOC?
Hoe is long integer allocation being used in LALLOC?
In MALLOC, how is size in bytes being allocated from the heap? Thanks
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
Although your description of these functions are essentially correct, it is worth pointing out that the GetProcessHeap
, HeapAlloc
, and HeapFree
functions are actually Win32 API functions, meaning that they are provided as part of the operating system for applications to call. Irvine's library has just provided prototypes for these functions to make them easier to call. As such, the semantics for these functions can be obtained directly from the horse's mouth by reading Microsoft's MSDN documentation (links above).
Like the documentation explains, it is a common pattern for an application that needs to allocate a moderate sized amount of memory to just obtain that memory from the process's default heap. This saves the need to create and overhead of managing a separate, private heap, just to make an allocation. The HeapAlloc
and HeapFree
(and similarly-named) functions are the ones you should be using in modern Windows programming, and not the obsolete GlobalAlloc
or LocalAlloc
functions that you sometimes still see used or referenced in Windows programming materials that haven't been updated for this century.
Now, in the code you have, since everything ultimately goes back to MALLOC
, let's start there. It sets up a stack frame, calls GetProcessHeap
, calls HeapAlloc
, and then tears down the stack frame. You should immediately see a bug. Remember how in your description of the GetProcessHeap
and HeapAlloc
functions, you were careful to describe what happens if they fail? Well, you were right; these functions can fail, and correctly written code should be checking for failures and handling them. This code does not.
In MALLOC, how is size in bytes being allocated from the heap?
The implementation of MALLOC
is pretty simple: all it really does is obtain a handle to the process heap and then use HeapAlloc
to allocate memory from that heap. So if you want to know how it works, go back to the documentation for HeapAlloc
. From this, we see that the first parameter is the handle to the heap (returned from GetProcessHeap
in 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 MALLOC
function on the stack. ([ebp + 4]
is the pointer to the calling function (where MALLOC
will ret
), and [ebp + 0]
is the original value of ebp
, saved upon entry to the MALLOC
function.)
In my opinion, this is another (minor) bug with the MALLOC
function: it is insufficiently documented! How are we supposed to know that it takes a parameter, much less what the size/type and meaning of that parameter are, without diving into its implementation? A function's basic purpose and interface should be documented right there 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 character allocation being used in CALLOC?
This is a simple macro wrapped around the MALLOC
function. Its purpose is basically to determine how many bytes to allocate, based on the number of characters you want to allocate space for, and then pass that value as the parameter to MALLOC
.
The CALLOC
macro takes a single parameter, size
, which is the number of characters you want to allocate space for. (By the way, I think that size
is a poor choice of name for this parameter, as it isn't very descriptive.)
It then multiplies the caller-specified size
by the actual number of bytes required by a character, which is determined at assembly time by the expression sizeof BYTE
. This will give the number of bytes that actually need to be allocated. (Now, since sizeof BYTE
is just 1, this is pretty silly and inefficient code! I guess it was written to be "portable", but come on—it's assembly language!)
Finally, it pushes the result (the number of bytes to allocate) onto the stack and calls MALLOC
to do the allocation.
And now that you understand how CALLOC
works, you should understand how all of these *ALLOC
macros work, since they're all the same. IALLOC
multiplies its parameter by the size of a short integer (sizeof WORD
) to arrive at the actual number of bytes that need to be allocated, while LALLOC
multiplies its parameter by the size of a long integer (sizeof DWORD
).
(Note that, although the multiplications in these other macros are necessary, they are also inefficient. sizeof WORD
== 2, so you could just do a left-shift by 1. Or, better yet, an addition of the value to itself. sizeof DWORD
== 4, so that's a left-shift by 2. Adds and shifts are much faster to execute than multiplications.)