2010-06-05 4 views
3

J'essaie d'obtenir une meilleure compréhension de l'assemblée, et je suis un peu confus sur la façon d'appeler récursive fonctions quand je dois traiter avec des registres, popping/pousser, etc.Récursion dans l'assemblage?

J'Embedding assembleur x86 en C++. Ici j'essaye de faire une méthode qui donnée un tableau d'entiers construira une liste liée contenant ces entiers dans l'ordre qu'ils apparaissent dans le tableau.

Je fais cela en appelant une fonction récursive:

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

-head: tête de la liste

-data: le nombre qui sera inséré à la fin d'une liste

-newElem: pointe vers l'emplacement en mémoire où je vais stocker le nouvel élément (champ de données)

Mon problème est que je continue d'écraser les registres au lieu d'un typi liste liée par cal. Par exemple, si je lui donne un tableau {2,3,1,8,3,9} ma liste-liée retournera le premier élément (tête) et seulement le dernier élément, parce que les éléments continuent de s'écrire après la tête n'est plus nul.

Voici donc ma liste chaînée ressemble à quelque chose comme: 2 -> 9 au lieu de 2 -> 3 -> 1 -> 8 -> 3 -> 9

Je me sens comme ne saisissez pas comment organiser et gérer les registres. newElem est dans EBX et ne cesse de se réécrire. Merci d'avance!

Répondre

2

La réponse la plus générique à toute question «comment faire» liée à l'assembleur est: gcc -S. Si vous avez des doutes sur quelque chose, jetez juste un coup d'oeil sur la façon dont un compilateur C correct traduit cela en un code de niveau inférieur.

Dans votre cas, vous devez gérer vos variables locales sur une trame de pile. Utilisez les registres uniquement pour les valeurs qui ne doivent pas survivre après un appel de sous-routine externe.

7

Il est difficile de donner une réponse sans avoir vu votre code asm. Ma première pensée est qu'il n'y a pas besoin de fonctions récursives quand il s'agit de listes liées.

Quoi qu'il en soit, la manière générale de conserver les registres à travers des appels de fonction est de les pousser sur la pile et les pop après:

; 
; 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

Essayez quelque chose comme ce que votre code asm

__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 
} 

EDIT : Juste couru cela et a réalisé que cela ne fonctionne pas. Il donne accès à la violation de lecture/écriture des erreurs de localisation. Mais j'espère que cela vous donnera un début, peut-être que quelqu'un pourra le nettoyer un peu.