动态堆分配混乱
Dynamic Heap Allocation Confusion
以下是 Assembly Kip Irvine 一书中提供的代码。
我想知道这段代码在做什么。我明白
getProcessHeap returns 程序现有的 32 位整数句柄
EAX中的堆区。如果函数成功,它将 return
EAX 中堆的句柄。如果失败,EAX 中的 return 值
为空
HeapAlloc 从堆中分配一块内存。如果成功,
EAX 中的 return 值包含内存块的地址。如果它
失败,EAX 中的 returned 值为 NULL。
如何在 CALLOC 中使用字符分配?
IALLOC 中如何使用整数分配?
LALLOC 中是否使用了长整数分配?
在 MALLOC 中,如何从堆中分配以字节为单位的大小?谢谢
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
虽然您对这些函数的描述基本上是正确的,但值得指出的是 GetProcessHeap
, HeapAlloc
, and HeapFree
函数实际上是 Win32 API 函数,这意味着它们作为操作系统的一部分提供给调用的应用程序。 Irvine 的库刚刚为这些函数提供了原型,以便于调用它们。因此,这些函数的语义可以通过阅读 Microsoft 的 MSDN 文档(上面的链接)直接从马口中获得。
正如文档所解释的那样,对于需要分配中等大小的内存以仅从进程的默认堆中获取该内存的应用程序来说,这是一种常见模式。这节省了创建和管理单独的私有堆的需要,只是为了进行分配。 HeapAlloc
和 HeapFree
(以及类似名称的)函数是您应该在现代 Windows 编程中使用的函数,而不是您有时仍然看到使用或在本世纪未更新的 Windows 编程材料中引用。
现在,在您拥有的代码中,由于一切最终都会回到 MALLOC
,让我们从这里开始。它建立一个栈帧,调用GetProcessHeap
,调用HeapAlloc
,然后拆除栈帧。你应该立即看到一个错误。还记得在您对 GetProcessHeap
和 HeapAlloc
函数的描述中,您是如何仔细描述它们失败时会发生什么情况的吗?嗯,你是对的;这些功能可能会失败,正确编写的代码应该检查失败并处理它们。此代码没有。
In MALLOC, how is size in bytes being allocated from the heap?
MALLOC
的实现非常简单:它真正做的就是获取进程堆的句柄,然后使用 HeapAlloc
从该堆分配内存。所以如果你想知道它是如何工作的,回到the documentation for HeapAlloc
。从这里,我们看到第一个参数是堆的句柄(从 eax
中的 GetProcessHeap
返回),第二个参数是控制分配的标志的按位组合(在本例中为 8 , 或 HEAP_ZERO_MEMORY
), 第三个参数是要分配的字节数 (在本例中, [ebp + 8]
).
[ebp + 8]
读取传递给堆栈上的 MALLOC
函数的第一个(并且可能是唯一的)参数。 ([ebp + 4]
是指向调用函数的指针(其中 MALLOC
将 ret
),而 [ebp + 0]
是 ebp
的原始值,在进入MALLOC
函数。)
在我看来,这是 MALLOC
函数的另一个(小)错误:没有足够的文档记录!我们应该如何知道它需要一个参数,更不用说 size/type 和该参数的含义,而不深入研究它的实现?函数的基本用途和接口应该在代码中使用注释进行记录。
因此,您问题的答案是,MALLOC
分配的字节数与您要求分配的字节数一样多。
How is character allocation being used in CALLOC?
这是一个围绕 MALLOC
函数的简单宏。它的目的基本上是根据您要分配 space 的字符数来确定要分配多少字节,然后将该值作为参数传递给 MALLOC
.
CALLOC
宏采用单个参数 size
,这是您要为其分配 space 的字符数。 (顺便说一下,我认为 size
这个参数的名称选择不当,因为它的描述性不强。)
然后它将调用者指定的 size
乘以字符所需的实际字节数,该字节数在汇编时由表达式 sizeof BYTE
确定。这将给出实际需要分配的字节数。 (现在,因为 sizeof BYTE
只是 1,这是非常愚蠢和低效的代码!我猜它被写成 "portable",但是得了吧——它是汇编语言!)
最后,它将结果(要分配的字节数)压入堆栈并调用 MALLOC
进行分配。
现在您了解了 CALLOC
的工作原理,您应该了解 所有 这些 *ALLOC
宏的工作原理,因为它们都是一样的. IALLOC
将其参数乘以一个短整数的大小 (sizeof WORD
) 以得出实际需要分配的字节数,而 LALLOC
将其参数乘以一个短整数的大小长整型 (sizeof DWORD
).
(请注意,尽管这些其他宏中的乘法是必要的,但它们的效率也很低。sizeof WORD
== 2,因此您可以左移 1。或者,更好的是,值本身的加法。sizeof DWORD
== 4,所以这是左移 2。加法和移位比乘法执行起来快得多。)
以下是 Assembly Kip Irvine 一书中提供的代码。 我想知道这段代码在做什么。我明白 getProcessHeap returns 程序现有的 32 位整数句柄 EAX中的堆区。如果函数成功,它将 return EAX 中堆的句柄。如果失败,EAX 中的 return 值 为空
HeapAlloc 从堆中分配一块内存。如果成功, EAX 中的 return 值包含内存块的地址。如果它 失败,EAX 中的 returned 值为 NULL。
如何在 CALLOC 中使用字符分配?
IALLOC 中如何使用整数分配?
LALLOC 中是否使用了长整数分配?
在 MALLOC 中,如何从堆中分配以字节为单位的大小?谢谢
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
虽然您对这些函数的描述基本上是正确的,但值得指出的是 GetProcessHeap
, HeapAlloc
, and HeapFree
函数实际上是 Win32 API 函数,这意味着它们作为操作系统的一部分提供给调用的应用程序。 Irvine 的库刚刚为这些函数提供了原型,以便于调用它们。因此,这些函数的语义可以通过阅读 Microsoft 的 MSDN 文档(上面的链接)直接从马口中获得。
正如文档所解释的那样,对于需要分配中等大小的内存以仅从进程的默认堆中获取该内存的应用程序来说,这是一种常见模式。这节省了创建和管理单独的私有堆的需要,只是为了进行分配。 HeapAlloc
和 HeapFree
(以及类似名称的)函数是您应该在现代 Windows 编程中使用的函数,而不是您有时仍然看到使用或在本世纪未更新的 Windows 编程材料中引用。
现在,在您拥有的代码中,由于一切最终都会回到 MALLOC
,让我们从这里开始。它建立一个栈帧,调用GetProcessHeap
,调用HeapAlloc
,然后拆除栈帧。你应该立即看到一个错误。还记得在您对 GetProcessHeap
和 HeapAlloc
函数的描述中,您是如何仔细描述它们失败时会发生什么情况的吗?嗯,你是对的;这些功能可能会失败,正确编写的代码应该检查失败并处理它们。此代码没有。
In MALLOC, how is size in bytes being allocated from the heap?
MALLOC
的实现非常简单:它真正做的就是获取进程堆的句柄,然后使用 HeapAlloc
从该堆分配内存。所以如果你想知道它是如何工作的,回到the documentation for HeapAlloc
。从这里,我们看到第一个参数是堆的句柄(从 eax
中的 GetProcessHeap
返回),第二个参数是控制分配的标志的按位组合(在本例中为 8 , 或 HEAP_ZERO_MEMORY
), 第三个参数是要分配的字节数 (在本例中, [ebp + 8]
).
[ebp + 8]
读取传递给堆栈上的 MALLOC
函数的第一个(并且可能是唯一的)参数。 ([ebp + 4]
是指向调用函数的指针(其中 MALLOC
将 ret
),而 [ebp + 0]
是 ebp
的原始值,在进入MALLOC
函数。)
在我看来,这是 MALLOC
函数的另一个(小)错误:没有足够的文档记录!我们应该如何知道它需要一个参数,更不用说 size/type 和该参数的含义,而不深入研究它的实现?函数的基本用途和接口应该在代码中使用注释进行记录。
因此,您问题的答案是,MALLOC
分配的字节数与您要求分配的字节数一样多。
How is character allocation being used in CALLOC?
这是一个围绕 MALLOC
函数的简单宏。它的目的基本上是根据您要分配 space 的字符数来确定要分配多少字节,然后将该值作为参数传递给 MALLOC
.
CALLOC
宏采用单个参数 size
,这是您要为其分配 space 的字符数。 (顺便说一下,我认为 size
这个参数的名称选择不当,因为它的描述性不强。)
然后它将调用者指定的 size
乘以字符所需的实际字节数,该字节数在汇编时由表达式 sizeof BYTE
确定。这将给出实际需要分配的字节数。 (现在,因为 sizeof BYTE
只是 1,这是非常愚蠢和低效的代码!我猜它被写成 "portable",但是得了吧——它是汇编语言!)
最后,它将结果(要分配的字节数)压入堆栈并调用 MALLOC
进行分配。
现在您了解了 CALLOC
的工作原理,您应该了解 所有 这些 *ALLOC
宏的工作原理,因为它们都是一样的. IALLOC
将其参数乘以一个短整数的大小 (sizeof WORD
) 以得出实际需要分配的字节数,而 LALLOC
将其参数乘以一个短整数的大小长整型 (sizeof DWORD
).
(请注意,尽管这些其他宏中的乘法是必要的,但它们的效率也很低。sizeof WORD
== 2,因此您可以左移 1。或者,更好的是,值本身的加法。sizeof DWORD
== 4,所以这是左移 2。加法和移位比乘法执行起来快得多。)