2010-06-05 75 views
3

我試圖更好地掌握程序集,我有點困惑如何遞歸調用函數,當我不得不處理寄存器,彈出/推動等。彙編中的遞歸?

我正在嵌入x86程序集C++。在這裏,我正在試圖讓一個給定一個整數數組的方法按照它們出現在數組中的順序建立一個包含這些整數的鏈表。

我通過調用遞歸函數這樣做:

insertElem (struct elem *head, struct elem *newElem, int data) 

-head:列表的頭

-data:將在列表

的末尾插入數

-newElem:指向內存中我將存儲新元素的位置(數據字段)

我的問題是我一直覆蓋寄存器而不是typi cal鏈表。 例如,如果我給它一個數組{2,3,1,8,3,9},我的鏈表將返回第一個元素(頭),並且只返回最後一個元素,因爲元素在頭後保持相互覆蓋不再爲空。

所以在這裏我的鏈接列表看起來像: 2 - > 9,而不是2 - > 3 - > 1 - > 8 - > 3 - > 9

我覺得像我沒有掌握如何組織和處理寄存器。 newElem在EBX中,只是不斷被重寫。提前致謝!

回答

2

任何彙編相關的「如何」問題的最一般的答案是:gcc -S。如果您對任何事情都有疑問,只需看看體面的C編譯器如何將其轉換爲較低級別的代碼。

你的情況,你需要維護你的本地變量在堆棧幀。任何外部子程序調用後,只使用寄存器的值不需要存活。

7

很難在沒有看到您的asm代碼的情況下給出答案。我首先想到的是,在處理鏈表時,不需要遞歸函數。

總之,要保持寄存器在函數調用的一般方法是將他們推入堆棧且隨後彈出他們:

; 
; ebx = current element 
; 
TraverseList: 

    ; If this is the end of the list we can skip the recursive invocation 
    cmp [ebx+next], 0 
    je NoNextElement 

    push ebx    ; Save current element (ebx) on stack 
    mov ebx, [ebx+next] ; Put next element in ebx 
    call TraverseList ; Recursive invocation 
    pop ebx    ; Restore current element (ebx) from stack 

NoNextElement: 

    ; Do stuff with the current element (ebx) 
    ... 
    ret 
0

嘗試這樣的事情作爲你的彙編代碼

__asm{ 
     mov ebx, dword ptr[esp+4] //head 
     mov ecx, dword ptr[esp+8] //newElem 
     mov edx, dword ptr[esp+12] // data 

    cmp [ebx+4], 0 
    je NO_NEXT_ELEMENT 

    mov ebx, [ebx+4] 
    mov ecx, [ecx+4] 

    push edx 
    push ecx 
    push ebx 
    call insertElem 
    pop ebx 
    pop ecx 
    pop edx 


NO_NEXT_ELEMENT: 


    mov dword ptr[ebx+4], ecx 
    mov dword ptr[ecx], edx 
    mov [ecx+4], 0 

    ret 
} 

編輯:只是跑這個,並意識到這是行不通的。它會導致訪問衝突讀取/寫入位置錯誤。但希望它給你一個開始,也許有人可以把它清理一下。