其实我有两个问题有些联系。
我使用的Windows功能是:
我正在使用 Irvine32 库和 Visual Studio 2022 作为我的 IDE。这是我将用来讨论问题的代码:
; main.asm
INCLUDE Irvine32.inc
.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode: DWORD
.data
testString BYTE "HELLO", 0
.code
main PROC
MOV esi, OFFSET testString
CALL StringHeapAlloc
INVOKE ExitProcess, 0
main ENDP
; --------------------------------------------------------------------
; StringHeapAlloc
;
; This function will allocate memory in the heap and
; RECEIVES: ESI
; RETURNS: EAX contains the heap handle;
; EBX contains the array address
; REQUIRES: ESI contains the address to the string being copied
; --------------------------------------------------------------------
StringHeapAlloc PROC USES eax esi
.data
MAX_STRING_SIZE = 20
; Dynamic Memory Information
hHandle DWORD ? ; contains the heap handle
pHeap DWORD ? ; contains the pointer to the memory allocated
dwFlag DWORD HEAP_ZERO_MEMORY ; contains the flags for allocating memory
dwByte DWORD MAX_STRING_SIZE + 1 ; contains the number of bytes to allocate
.code
; gets heap handle for heap allocation
INVOKE GetProcessHeap
MOV hHandle, eax ; storing heap handle
; allocates memory in the heap for the string
INVOKE HeapAlloc, hHandle, dwFlag, dwByte
MOV pHeap, eax ; storing pointer to array
; copies string into the allocated memory
INVOKE Str_copy, esi, pHeap
RET
StringHeapAlloc ENDP
END main
在汇编中,我使用的动态内存分配的方法是:
我知道指向堆的指针只是指向分配的特定内存位置的地址。不太明白heap handle是什么。我使用 VS 调试器做了一些调查,发现:
堆句柄是006E0000。指向堆的指针是006E6568。我注意到每次运行代码时,堆句柄似乎都在指向堆的指针内。如果我们类似地考虑这个问题,堆句柄是否就像一条街道上的房屋地址为 19000,而指向堆的指针就像那条街道上居民的地址(19000、19001 等)?
我总能从指向堆的指针导出堆句柄吗?在我运行代码的例子中,堆句柄是006E0000,堆指针是006E6568。 堆句柄总是指向堆的指针中的前4个字节吗?
要释放内存,我需要使用 HeapFree。但是,该函数要求我有 heap handle 和 pointer to the heap。现在,每次我动态分配内存时,我都会将堆句柄存储在一个包含堆句柄的数组中,并将指向堆的指针存储在一个包含指针的数组中。如果 heap handle 可以导出,那么我可以摆脱那个额外的数组来存储堆句柄。
编辑:抱歉,我对代码做了一个小修改。在主函数中将 EDX 更改为 ESI。 testString 的偏移量应该存储在 ESI 中,以便 StringHeapAlloc 工作。