(MASM x86) In assembly, what is the difference between heap handle and pointer to the heap?

huangapple go评论98阅读模式
英文:

(MASM x86) In assembly, what is the difference between heap handle and pointer to the heap?

问题

我实际上有两个有些相关的问题。

  1. 在汇编语言中,堆句柄(heap handle)和指向堆的指针之间有什么区别?
  2. 能否从指向堆的指针确定堆句柄?

我正在使用的Windows函数是:

我使用的是Irvine32库,并且将Visual Studio 2022作为我的IDE。以下是我将用于讨论这些问题的代码:

  1. ; main.asm
  2. INCLUDE Irvine32.inc
  3. .386
  4. .model flat, stdcall
  5. .stack 4096
  6. ExitProcess PROTO, dwExitCode: DWORD
  7. .data
  8. testString BYTE "HELLO", 0
  9. .code
  10. main PROC
  11. MOV esi, OFFSET testString
  12. CALL StringHeapAlloc
  13. INVOKE ExitProcess, 0
  14. main ENDP
  15. ; --------------------------------------------------------------------
  16. ; StringHeapAlloc
  17. ;
  18. ; 此函数将在堆中分配内存,并将给定的字符串复制到分配的内存位置。
  19. ; 接收:ESI
  20. ; 返回:EAX 包含堆句柄;
  21. ; EBX 包含数组地址
  22. ; 需要:ESI 包含要复制的字符串的地址
  23. ; --------------------------------------------------------------------
  24. StringHeapAlloc PROC USES esi
  25. .data
  26. MAX_STRING_SIZE = 20
  27. ; 动态内存信息
  28. hHandle DWORD ? ; 包含堆句柄
  29. pHeap DWORD ? ; 包含指向已分配内存的指针
  30. dwFlag DWORD HEAP_ZERO_MEMORY ; 包含分配内存的标志
  31. dwByte DWORD MAX_STRING_SIZE + 1 ; 包含要分配的字节数
  32. .code
  33. ; 获取用于堆分配的堆句柄
  34. INVOKE GetProcessHeap
  35. MOV hHandle, eax ; 存储堆句柄
  36. ; 在堆中为字符串分配内存
  37. INVOKE HeapAlloc, hHandle, dwFlag, dwByte
  38. MOV pHeap, eax ; 存储数组的指针
  39. ; 将字符串复制到分配的内存中
  40. INVOKE Str_copy, esi, pHeap
  41. ; 返回堆句柄和指向句柄的指针
  42. MOV eax, hHandle
  43. MOV ebx, pHeap
  44. RET
  45. StringHeapAlloc ENDP
  46. END main

Q1

在汇编语言中,我正在使用的动态内存分配方法是:

  1. 使用 GetProcessHeap 生成 堆句柄
  2. 使用 HeapAlloc 分配内存。(这一步会给我一个 指向堆 的指针)
  3. 对内存进行操作。
  4. 使用 HeapFree 释放内存。

我理解 指向堆 只是分配的特定内存位置的地址。我不太明白 堆句柄 是什么。我对Visual Studio调试器进行了一些调查,发现:

堆句柄为006E0000。指向堆的指针为006E6568。我注意到堆句柄似乎总是在指向堆的指针内的前四个字节。如果我们类比这样思考,堆句柄 就像一个街道,其房屋地址为19000,而 指向堆 就像该街道上居民的地址(19000、19001等)。

Q2

我能否始终从 指向堆 推导出 堆句柄?在我运行代码的示例中,堆句柄 是006E0000,而 指向堆 是006E6568。 堆句柄 是否总是指向堆的指针内的前四个字节?

要释放内存,我需要使用 HeapFree。然而,该函数要求我有 堆句柄指向堆。现在,每次我动态分配内存,我都将堆句柄存储在一个包含堆句柄的数组中,而将指向堆的指针存储在一个包含指针的数组中。如果可以推导出 堆句柄,那我就可以摆脱额外的数组来存储堆句柄。

英文:

I actually have two questions that are somewhat connected.

  1. In assembly, what is the difference between heap handle and pointer to the heap?
  2. Can the heap handle be determined from the pointer to the heap?

The Windows functions I am using are:

I am using the Irvine32 library, and Visual Studio 2022 as my IDE. Here is the code I will be using to talk about the questions:

  1. ; main.asm
  2. INCLUDE Irvine32.inc
  3. .386
  4. .model flat, stdcall
  5. .stack 4096
  6. ExitProcess PROTO, dwExitCode: DWORD
  7. .data
  8. testString BYTE "HELLO", 0
  9. .code
  10. main PROC
  11. MOV esi, OFFSET testString
  12. CALL StringHeapAlloc
  13. INVOKE ExitProcess, 0
  14. main ENDP
  15. ; --------------------------------------------------------------------
  16. ; StringHeapAlloc
  17. ;
  18. ; This function will allocate memory in the heap and copy, a given
  19. ; string, into the allocated memory location.
  20. ; RECEIVES: ESI
  21. ; RETURNS: EAX contains the heap handle;
  22. ; EBX contains the array address
  23. ; REQUIRES: ESI contains the address to the string being copied
  24. ; --------------------------------------------------------------------
  25. StringHeapAlloc PROC USES esi
  26. .data
  27. MAX_STRING_SIZE = 20
  28. ; Dynamic Memory Information
  29. hHandle DWORD ? ; contains the heap handle
  30. pHeap DWORD ? ; contains the pointer to the memory allocated
  31. dwFlag DWORD HEAP_ZERO_MEMORY ; contains the flags for allocating memory
  32. dwByte DWORD MAX_STRING_SIZE + 1 ; contains the number of bytes to allocate
  33. .code
  34. ; gets heap handle for heap allocation
  35. INVOKE GetProcessHeap
  36. MOV hHandle, eax ; storing heap handle
  37. ; allocates memory in the heap for the string
  38. INVOKE HeapAlloc, hHandle, dwFlag, dwByte
  39. MOV pHeap, eax ; storing pointer to array
  40. ; copies string into the allocated memory
  41. INVOKE Str_copy, esi, pHeap
  42. ; returning heap handle and pointer to handle
  43. MOV eax, hHandle
  44. MOV ebx, pHeap
  45. RET
  46. StringHeapAlloc ENDP
  47. END main

Q1

In assembly, the method of dynamic memory allocation I am using is:

  1. Use GetProcessHeap to generate a heap handle.
  2. Allocate memory using HeapAlloc. (this step will give me a pointer to the heap)
  3. Do something with the memory.
  4. Free the memory using HeapFree.

I understand that the pointer to the heap is just the address to a specific memory location that was allocated. I do not quite understand what the heap handle is. I did a bit of investigation using VS debugger, and found that:

The heap handle is 006E0000. The pointer to the heap is 006E6568. I noticed that the heap handle seems to be within the pointer to the heap every time I ran the code. If we were thinking of this analogously, is the heap handle like a street with houses that have addresses 19000, and the pointer to the heaps like the addresses to the residents on that street (19000, 19001, etc.)?

Q2

Can I always derive the heap handle from the pointer to the heap? In the example, where I ran the code, the heap handle was 006E0000 and the pointer to the heap was 006E6568. Is the heap handle always the first 4 bytes in the pointer to the heap?

To free the memory, I would need to use HeapFree. However, that function requires that I have the heap handle and pointer to the heap. Right now, every time I dynamically allocate memory, I store the heap handles in an array containing heap handles and the pointers to the heap to an array containing pointers. If the heap handle can be derived then I could get rid of that extra array to store heap handles.

Edit: Changed EDX to ESI in the main function. The offset of testString should be stored in ESI for StringHeapAlloc to work.

Edit: Completed documentation of StringHeapAlloc function and added "MOV eax, hHandle" and "MOV ebx, pHeap" at end of StringHeapAlloc function. It should not affect the original questions.

答案1

得分: 2

Handles of all kinds are just values. They can be pointers but in some cases are just integers. (Pointers are generally preferred because they allow different types of handles to type-differentiate in languages that have the concept of type - like C).

The point of the above is that you do not worry about what sort of structure backs a pointer. It is simply a value stored by the calling code and understood by the called code.

Note that most windows handles are of the form

  1. struct HNAME__ { int unused };
  2. typedef HNAME__ * HNAME;

but you never use the 'HNAME__' struct, you simply use the HNAME value the API hands you.

英文:

Handles of all kinds are just values. They can be pointers but in some cases are just integers. (Pointers are generally [preferred because they allow different types of handles to type-differentiate in languages that have the concept of type - like C).

The point of the above is that you do not worry about what sort of structure backs a pointer. It is simply a value stored by the calling code and understood by the called code.

Note that most windows handles are of the form

  1. struct HNAME__ { int unused };
  2. typedef HNAME__ * HNAME;

but you never use the 'HNAME__' struct, you simply use the HNAME value the API hands you.

huangapple
  • 本文由 发表于 2023年4月20日 09:35:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76059934.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定