【问题标题】:Assembly Dynamic memory allocation x86汇编动态内存分配 x86
【发布时间】:2018-05-11 10:59:29
【问题描述】:

我正在尝试通过我的字符串查询过程中的 calloc 宏分配 50 个字节。问题是我不知道该怎么做,而且我尝试做的方式肯定是错误的。我尝试将 50 传递到 EAX 寄存器,然后调用 calloc 宏。我的程序符合但就是这样。所以我的问题是如何正确使用这些程序?我是否通过将值移动到寄存器中来玩寄存器?一旦我取回分配的空间,该空间在哪里?寄存器?我不能使用任何全局变量,这就是本练习的重点。非常感谢您的帮助。

    INCLUDE Irvine32.inc

    ; Macro to ease the use of alloc procedure 

    mAlloc      Macro      Value
    Push        offset  value
    Call        ALLOC
    endM

   ;Macro to ease the use of memFree
   free       Macro      value 
   push       offset     value 
   Call       memFree
   endM


   ; Macro to ease the use of the alloc procedure, for character data
   cAlloc      Macro     Value
   mov         eax, sizeof BYTE
   imul        eax, Value  

   Push      eax
   Call      alloc
   endM

   ;Macro to ease the use of of the alloc procedure for integer Data
   iAlloc      Macro     Value
   mov         eax, sizeof WORD
   imul        eax, Value 

   Push      eax 
   Call      mAlloc
   endM

   ;Macro to ease the use of the alloc for long interger DATA 
   lAlloc      Macro      Value
   mov         eax, sizeof DWORD
   imul        eax, Value 

   Push       OFFSET   value
   Call       mAlloc
   endM

   ;Macro for string query 
   STRQRYM    Macro      value
   Push       OFFSET value
   Call       strQry
   ENDM

   .data
   HeapHandle TEXTEQU <[EBP - 4]>
   Prompt    Byte "Please enter your name: ", 0
   Message   Byte "the name you entered is: ", 0


   .code
   ALLOC       PROC
   push        EBP
   MOV         EBP, ESP
   SUB         ESP, 4

   INVOKE      GetprocessHeap
   ;MOV        HeapHandle, EAX
   INVOKE      HeapAlloc, HeapHandle, HEAP_ZERO_MEMORY,[EBP + 8]

   ADD         ESP, 4
   POP         EBP
   RET         4
   ALLOC       ENDP

   memFree     PROC
   push        ebp
   mov         ebp, esp

   INVOKE      GetProcessHeap
   ; mov heap handle to eax? 
   Invoke       HeapFree, EAX, 0, [EBP + 8]

   pop         ebp
   RET         4
   memFree     ENDP

   strQry      PROC
   Push        EBP
   Mov         EBP, ESP

   Push        EDX
   push        ECX

   ;print string 
   Mov         EDX, [EBP + 8]
   Call        writeString

   ; create byte and push 50 characters into a variable 
   Mov         ECX, 50  

   mov         eax, 50
   calloc      eax 
   Call        readString


     Pop         ECX
     Pop         EDX
     Pop         EBP

     Ret         4



      strQry      ENDP

      MAIN        PROC

      ;test strQRY allocate 50 bytes 
    ; MEM should free memory at adress and send an indication back 
    that it has happend
     ;test each proc and Macro approrpiately (display)

     STRQRYM     prompt


      EXIT
      Main ENDP
      END Main

【问题讨论】:

  • calloc eax 将会是一个惊喜。
  • 为什么不imul eax, Value, sizeof x?或者要求它是一个寄存器,这样你就可以使用lea eax, [Value * sizeof x],而不是使用大小为 2 的乘法指令。

标签: assembly x86 irvine32


【解决方案1】:
   ; Macro to ease the use of the alloc procedure, for character data
   cAlloc      Macro     Value
   mov         eax, sizeof BYTE
   imul        eax, Value  

   Push      eax
   Call      alloc
   endM

结合用法:

calloc      eax 

将产生代码:

   mov       eax, 1
   imul      eax, eax  ; eax = 1
   push      eax
   call      alloc

...可能不是您所期望的,而是使用edx作为输入...或者停止使用宏,而是将它们变成常规子例程,然后call它们(往往更容易阅读+调试,宏从源代码中改变了很多输出机器代码,除了无法衡量的性能之外没有任何好处,在这种情况下这是没有意义的,因为动态分配已经是非常慢的操作,额外的call不会破坏它)。

还有什么不好的:

    push 50
    call alloc

它需要另一个宏,比如cAlloc


关于“不允许使用全局变量”

然后在堆栈上分配一些空间,例如 sub esp,100h 以拥有从 esp+0esp+255 的 256 字节空间(如果您确实以常用方式将堆栈帧设置为 ebp,并且您做了 sub esp,100h之后,本地保留空间在ebp-100h .. ebp-1h

HeapHandle 甚至建议使用这种用法,尽管我会删除它并在代码中编写 [ebp-4],而字符串“HeapHandle”使源代码阅读器很难看到实际生成的机器代码是什么.我通常不赞成在汇编中使用宏,这是 IMO 非常糟糕的做法。通常唯一合法的汇编用法是用于性能编程,您可以在汇编中编写一小部分以性能为重点的代码,从高级语言调用。那时,在您希望它尽可能简单的小程序集中,宏正在向读者隐藏生成的机器代码,这使得审查/修改更加困难。并且使用宏没有任何优势(如果在没有宏的汇编中编写代码太长/太无聊,那么汇编的选择很可能是错误的决定,那部分代码应该用 HLPL 编写)。

编辑:被注释掉的 ;MOV HeapHandle, EAX 也可能是错误的,检查 Irvine lib 文档,堆句柄是如何返回的,但很可能在 eax 中,所以你的下一个 invoke 使用 [ebp-4] 将在堆栈中使用一些随机值,而不是句柄值(当 mov 被注释时)。

如果您想使用所有这些宏魔法,那么可能甚至不必费心发布原始源代码,而是发布列表文件或反汇编,还可以使用带有反汇编视图的调试器来更好地了解您真正对计算机所做的事情.

最后,如果您只需要 50 个字节,将它们分配到堆栈上可能会简单得多(仅通过 sub esp,... 方式)。千字节大小的大小非常适合堆栈使用,100+ kiB 大小可能更适合堆使用。因此,您可以使用 alloc + free 为您节省这么少的内存。

无论如何,你应该同时学习+练习,所以它仍然是有效的练习,我只是不建议将它用于生产,如果大规模完成,类似 50B 的分配很快就会破坏堆管理器。

【讨论】:

    猜你喜欢
    • 2021-02-19
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多