2011-12-15 10 views
1

Я пытаюсь экспериментировать с malloc и свободно в ассемблере (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 
+1

Вы копируете-вставьте-сбой: dealloc_2 выполняет 'test r11, r11', но это должен быть' test r12, r12' (если требуется вообще) –

ответ

4

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

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

Если второй 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, чтобы они могли использоваться для освобождения. EDIT: И я бы проверял, является ли это правильным способом передачи параметров через стек (опять же, см. Документацию к компилятору).

EDIT: вы тестируете r11 для 0 непосредственно перед вторым free(). Это должно быть r12. Но free() на самом деле не возражает против получения указателей NULL. Таким образом, эти проверки можно удалить.

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

2

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

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

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

3

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

+1

Да, конечно, ему даже не нужны аргументы в стеке. Поэтому мое «исправление ошибок» с использованием qword действительно не исправляет что-то – hirschhornsalz

Смежные вопросы