【问题标题】:Malloc and Free multiple arrays in assemblyMalloc 和 Free 汇编中的多个数组
【发布时间】:2011-12-15 11:09:28
【问题描述】:

我正在尝试在汇编代码(NASM,64 位)中使用 malloc 和 free。

我试图 malloc 两个数组,每个数组都有 2 个 64 位数字的空间。现在我希望能够写入它们的值(不确定访问它们是否/如何准确工作),然后在整个程序结束时或在任何时候出现错误的情况下,释放内存。

如果有一个数组,我现在可以正常工作,但是一旦我添加另一个数组,它在第一次尝试释放任何内存时失败:(

我的代码目前如下:

extern printf, malloc, free


LINUX        equ     80H      ; interupt number for entering Linux kernel
EXIT         equ     60       ; Linux system call 1 i.e. exit ()

segment .text
    global      main

main:
    push dword 16       ; allocate 2 64 bit numbers
    call malloc
    add rsp, 4          ; Undo the push
    test  rax, rax      ; Check for malloc failure
    jz    malloc_fail
    mov r11, rax        ; Save base pointer for array

    ; DO SOME CODE/ACCESSES/OPERATIONS HERE

    push dword 16       ; allocate 2 64 bit numbers
    call malloc
    add rsp, 4          ; Undo the push
    test  rax, rax      ; Check for malloc failure
    jz    malloc_fail
    mov r12, rax        ; Save base pointer for array

    ; DO SOME CODE/ACCESSES/OPERATIONS HERE

malloc_fail:
    jmp dealloc

; Finish Up, deallocate memory and exit
dealloc:
    dealloc_1:
        test  r11, r11    ; Check that the memory was originally allocated
        jz    dealloc_2   ; If not, try the next block of memory
        push r11          ; push the address of the base of the array
        call free         ; Free this memory
        add rsp, 4
    dealloc_2:
        test  r12, r12
        jz    dealloc_end
        push r12
        call free
        add rsp, 4
dealloc_end:
    call os_return        ; Exit

os_return:
    mov  rax, EXIT
    mov  rdi, 0
    syscall

【问题讨论】:

  • 你复制粘贴失败:dealloc_2 是 test r11, r11 但它必须是 test r12, r12(如果需要的话)

标签: memory-management assembly x86-64 nasm


【解决方案1】:

我假设上面的代码正在调用 C 函数 malloc()free()...

如果第一个malloc() 失败,则在从malloc() 返回后,您将到达dealloc_1,其中包含r11r12 中的任何垃圾。

如果第二个malloc() 失败,则在从malloc() 返回后,您将带着r12 中的任何垃圾到达dealloc_1

因此,在进行第一次分配之前,您必须将 r11r12 归零。

由于这是 64 位模式,所有指针/地址和大小通常都是 64 位的。当您将其中一个传递给函数时,它必须是 64 位的。所以,push dword 16 不太正确。它应该是push qword 16。同样,当您从堆栈中删除这些参数时,您必须删除的字节数与您放在那里的字节数相同,因此add rsp, 4 必须更改为add rsp, 8

最后,我不知道malloc()free() 保留哪些寄存器,哪些不保留。您可能需要保存和恢复所谓的volatile registers(请参阅您的 C 编译器文档)。对于未显示的代码也是如此。它必须保留r11r12,以便它们可以用于释放。 编辑:我会检查它是否是通过堆栈传递参数的正确方法(再次,请参阅您的编译器文档)。

编辑:您在第二个 free() 之前为 0 测试 r11。应该是r12。但是free() 并不介意接收 NULL 指针。因此,可以删除这些检查。

注意你的代码。

【讨论】:

    【解决方案2】:

    您必须遵守x86-64 calling conventions:参数可能通过寄存器传递,在 malloc 的情况下,这将是大小的 RDI。正如已经指出的那样,您必须注意被调用函数保留了哪些寄存器。 (afaik 只有 RBP、RSP 和 R12-R15 在函数调用中保留)

    【讨论】:

    • 是的,当然,他甚至不需要堆栈上的参数。所以我使用 qword 的“错误修复”并没有真正解决问题
    【解决方案3】:

    至少有两个错误,因为你再次测试r11dealloc_2: 之后的行test r11,r11,但据说你想在这里测试r12。另外你想推一个qword,如果你是在 64 位模式下。

    释放根本不起作用的原因可能是因为您正在更改r11r12 的内容。

    并不是说不需要这两个测试,因为使用空指针调用free 是完全安全的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      相关资源
      最近更新 更多