Inline Assembler Problem



  • Ok ich muss number zu dem element addieren zu dem der pointer *element zeigt. *element und integer kommen von C code. Hab absolut keine Ahnung wie ich das machen kann. Danke schon mal im voraus fuer die Hilfe.

    __declspec(naked) list*
    ADD_CONSTANT_TO_LIST_ELEMENT (list *element, int number)
    {
    __asm {
    push ebx
    push ecx
    mov ebx,dword ptr[esp+12]
    mov ecx,dword ptr[esp+16]

    cmp ebx,0
    je END
    jmp ADDITION

    ADDITION:
    //code goes here

    pop ecx
    pop ebx
    ret

    END:
    mov eax,ebx
    pop ecx
    pop ebx
    ret

    }

    }



  • _asm    mov     eax, element
    _asm    add     [eax], number
    

    das reicht aus 🙂



  • danke fuer die Hilfe leider muss ich alle Werte vom Stack ziehn habs aber zum laufen gebracht hier ist der code:

    ADD_CONSTANT_TO_LIST_ELEMENT (list *element, int number)
    {
    __asm {
    push ebx
    push edx
    mov ebx,dword ptr[esp+12]
    mov edx,dword ptr[esp+16]
    cmp ebx,0
    je END
    mov ecx,dword ptr[ebx+4]
    add ecx,edx
    jmp END2

    END:
    pop edx
    pop ebx
    ret

    END2:
    mov dword ptr[ebx+4],ecx
    pop edx
    pop ebx
    ret

    }



  • ecx sollte vermutlich auch wiederhergestellt werden.
    die defintion deiner function hat einen rueckgabe-wert "list*" der durch "__declspec(naked) " in eax erwartet wird.
    den "end:"-block kannst du einsparen indem du gleich zu den unteren pops springst, womit das "jmp end2" entfaellt.


  • Mod

    es genügt ebx zu sichern. aus der syntax schlussfolgere ich mal, dass es sich um den microsoft compiler handelt. in dem falle sind eax, ecx und edx 'volatile', dürfen also verändert werden. daher dürfte es am sinnvolsten sein, gleich nur eax,ecx und edx zu verwenden - das geht hier ja problemlos - und das sichern von registern ganz zu unterlassen. andererseits ist das ja wohl ohnehin eine übungsaufgabe. die definition von list würde mich allerdings intressieren - wenn das nicht gerade ein typedef auf int ist, ist der code, so wie er jetzt ist, vermutlich eher sinnlos.



  • typedef struct list {
    struct list *next;
    int value;
    } list;

    das ist die list defenition

    Ich hab aber noch eine weiter frage . Ich muss eine Daten Struktur veraendern (Liste). Muss das element int valu in a_list finden und dann loeschen. Mein Problem ist das ich mit dem Befehl "mov eax,dword ptr[esi+ebx*4]" zwar die adresse der einzelnen Nodes bekomme aber nicht den Wert. Hat jemand von euch ne Ahnung wie ich den Wert bekommen kann fuer die einzelnen addressen? Vielen Dank

    _declspec(naked) list *
    DELETE_FROM_LIST (list * a_list, int value)
    {

    __asm {
    mov esi,dword ptr[esp+4]
    mov ecx,10
    xor ebx,ebx

    NEXT:

    mov eax,dword ptr[esi+ebx*4]
    inc ebx
    jmp NEXT
    ret

    }
    }



  • du hast ja die adresse (pointer) der liste in einem register, ueber dieses register kannst du auf die zwei elemente der struktur zugreifen:

    mov eax,[esp+4] // value
    mov ebx,[esp+0] // adresse der naechsten node
    

    ueber das register (hier ebx) in die du die neue adresse geladen hast, kannst du dann das naechste element ansprechen:

    mov eax,[ebx+4] // value
    

    usw...
    zum entfernen des aktuellen elements musst du den next-zeiger vom vorherigen (sofern existent) auf das naechste zeigen lassen und den speicher des aktuellen freigeben.


  • Mod

    jochen06 schrieb:

    typedef struct list {
    struct list *next;
    int value;
    } list;

    so kommen wir der sache schon näher. ich hab mir mal die freiheit genommen, die erste funktion und eine find funktion zu implementieren:

    typedef struct list
    {
        struct list *next;
        int value;
    } list;
    
    __declspec(naked) list* ADD_CONSTANT_TO_LIST_ELEMENT(list *element, int value)
    {
        __asm
        {
            mov     eax, [ esp + 4 ]        // element
            mov     edx, [ esp + 8 ]        // value
            test    eax, eax
            jz      exit_
            add     list::value[ eax ], edx // alternative syntax:  add	 [ eax ]list.value, edx
    exit_:
            ret
        }
    }
    
    __declspec(naked) list* FIND(list* a_list, int value)
    {
        __asm
        {
            mov     eax, [ esp + 4 ]        // a_list
            mov     edx, [ esp + 8 ]        // value
            jmp     start_
    loop_:
            mov     eax, list::next[ eax ]
    start_:
            test    eax, eax
            jz      exit_
            cmp     list::value[ eax ], edx
            jne     loop_
    exit_:
            ret
        }
    }
    

    die zeile wo ich eine alternative syntax angegeben habe, ist das intressante daran. im prinzip wollen wir einen ausdruck [eax+offsetof(list,value)] (nur ist offsetof ein C macro, das wir hier nat. nicht einsetzen können) - und es gibt auch ein paar syntaktische varianten, die der compiler hier akzetiert. die beiden, die ich oben gezeigt habe, haben allerdings den vorteil, dass sie auch der intel compiler für windows versteht - falls du jemals in verlegenheit gerätst, diesen benutzen zu wollen. die tradiotionelle methode der art

    (list ptr [eax]).value
    

    wie man sie in standalone assembler verwenden würde, scheitert an einigen beschränkungen des inline assemblers.


Anmelden zum Antworten