2011-12-15 38 views
1

我想用malloc和免費的彙編代碼(NASM,64位)實驗。Malloc和免費的多個數組在組裝

我試圖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`(如果需要的話) ) – 2011-12-15 12:36:30

回答

4

我假設上面的代碼調用C函數malloc()free() ...

如果1 malloc()失敗,你與任何垃圾是到達dealloc_1malloc()返回後的和r12

如果第二個malloc()失敗,則您從malloc()返回後抵達dealloc_1,並返回r12中的任何垃圾。

因此,您必須在執行第一次分配之前將r11r12置零。

由於這是64位模式,所有指針/地址和大小通常都是64位。當你將其中的一個傳遞給一個函數時,它必須是64位的。所以,push dword 16不太對。相反,它應該是push qword 16。同樣,當您從堆棧中刪除這些參數時,您必須刪除與您放置的字節數完全相同的字節數,因此add rsp, 4必須更改爲add rsp, 8

最後,我不知道哪些寄存器malloc()free()保留,哪些不是。您可能需要保存和恢復所謂的volatile registers(請參閱您的C編譯器文檔)。代碼未顯示也一樣。它必須保留r11r12,以便它們可以用於重新分配。 編輯:我會檢查它是否是通過堆棧傳遞參數的正確方法(再次參見您的編譯器文檔)。

編輯:您正在測試r11 0之前第二個free()。它應該是r12。但free()並不介意接收NULL指針。所以,這些檢查可以被刪除。

注意你的代碼。

2

至少有兩個錯誤,因爲你test r11,r11dealloc_2:後再次測試r11(行,但你理應想在這裏測試r12。另外,你要推一個四字,如果你是在64位模式。

取消分配完全不起作用的原因可能是因爲您正在更改r11r12的內容。

不是因爲兩個測試都不需要,因爲用空指針調用free是完全安全的。

3

您必須服從x86-64 calling conventions:參數可能會通過寄存器傳遞,對於大小爲RDI的malloc而言。正如已經指出的那樣,你必須注意被調用函數保存哪些寄存器。 (afaik只有RBP,RSP和R12-R15在函數調用中被保留)

+1

當然,他甚至不需要堆棧上的參數。所以我使用qword的「錯誤修復」並沒有真正解決問題 – hirschhornsalz 2011-12-15 12:39:11