Malloc и Free несколько массивов в сборке - PullRequest
1 голос
/ 15 декабря 2011

Я пытаюсь поэкспериментировать с malloc и свободным кодом ассемблера (NASM, 64 бит).

Я попытался распределить по двум массивам, в каждом из которых есть место для 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

Ответы [ 3 ]

4 голосов
/ 15 декабря 2011

Я предполагаю, что приведенный выше код вызывает функции C malloc() и free() ...

Если 1-й malloc() завершится неудачно, вы получите dealloc_1 с любым мусором в r11 и r12 после возврата из malloc().

Если 2-й malloc() не пройден, вы получите dealloc_1 с любым мусором в r12 после возвращения из malloc().

Поэтому перед выполнением первого выделения необходимо обнулить r11 и r12.

Поскольку это 64-разрядный режим, все указатели / адреса и размеры обычно являются 64-разрядными.,Когда вы передаете один из них в функцию, он должен быть 64-битным.Итак, push dword 16 не совсем верно.Это должно быть push qword 16 вместо этого.Аналогично, когда вы удаляете эти параметры из стека, вы должны удалить ровно столько байтов, сколько положили туда, поэтому add rsp, 4 должно измениться на add rsp, 8.

Наконец, я незнать, какие регистры malloc() и free() сохраняют, а какие нет.Вам может потребоваться сохранить и восстановить так называемый volatile registers (см. Документацию вашего компилятора C).То же самое относится и к коду, который не показан.Он должен сохранять r11 и r12, чтобы их можно было использовать для освобождения. РЕДАКТИРОВАТЬ : И я бы проверил, является ли это правильным способом передачи параметров через стек (снова, см. Документацию вашего компилятора).

РЕДАКТИРОВАТЬ : вытестирование r11 на 0 непосредственно перед вторым free().Это должно быть r12.Но free() не против получить указатели NULL.Таким образом, эти проверки могут быть удалены.

Обратите внимание на ваш код.

3 голосов
/ 15 декабря 2011

Вы должны соблюдать x86-64 соглашения о вызовах : аргументы могут передаваться через регистры, в случае malloc это будет RDI для размера. И, как уже указывалось, вы должны следить за тем, какие регистры сохраняются вызываемыми функциями. (afaik только RBP, RSP и R12-R15 сохраняются при вызове функций)

2 голосов
/ 15 декабря 2011

Есть как минимум две ошибки, потому что вы тестируете r11 снова (строка test r11,r11 после dealloc_2:, но вы, вероятно, хотели проверить r12 здесь. Кроме того, вы хотите нажать qword, если выв 64-битном режиме.

Причина, по которой освобождение не работает вообще, может заключаться в том, что вы меняете содержимое r11 или r12.

Не то, чтобы оба теста не былинеобходимо, так как совершенно безопасно вызывать free с нулевым указателем.

...