Inline Assembler unter VC++



  • Kann mir einer an einem simplen Beispiel zeigen wie man Inline Assembler unter VC++ benützt. (z.B. Ausgabe einer Zeichenkette...)



  • ach kommt bitte wenigstens etwas



  • Also wenn du z.b. einfach die ausgabefunktion printf benutzt gehts so:

    #include <stdio.h>
    
    const char output[] = "Hello, World\n";
    
    int main(int argc, char *argv[])
    {
        _asm
        {
            push offset output;
            call printf;
            add esp, 4;
        }
        return 0;
    }
    

    Sprich: adresse von der Variable output wird auf den Stack gelegt, printf aufgerufen und dann der Stack wieder zurechtgerückt 🙂



  • hallo, wie kommst du bei add esp, 4 gerade auf 4?



  • Moin, Moin...

    Mit dem Befehl add esp, 4 wird der Stack bereinigt. Bevor die Funktion printf aufgerufen wird, wird noch die Adresse der Zeichenkette(Parameter) auf den Stack gelegt. Von dort holt sich die Funktion printf die Adresse. Nachdem die Funktion ihre Aufgabe erledigt hat, muss der Parameter wieder vom Stack entfernt werden.
    Da eine Adresse(Zeiger) 4 Bytes beansprucht, wird zu dem Register esp einfach 4 dazugezählt(der Stack wächst von den hohen Adressen zu den niedrigen Adressen!!!!).

    Ciao...



  • Nochmal Moin...

    Hier noch ein Beispiel für Assembler in C:

    #include <stdio.h>
    #include <stdlib.h>
    
    char eingabe[81];
    int  laenge;
    
    int main()
    {
      printf("Einen Text eingeben: ");
      scanf("%s", eingabe);
    
      __asm
      {
        push ebx
        push ecx
    
        xor  eax, eax            // eax löschen
        lea  ebx, eingabe        // Adresse der Zeichenkette in ebx
    
    _j1:
        mov  cl, byte ptr [ebx]  // Zeichen holen
        or   cl, cl              // Zeichen = 0 ?
        je   _raus
    
        inc  eax                 // Anzahl der Zeichen + 1
        inc  ebx                 // Adresse + 1 --> nächstes Zeichen
    
        jmp  _j1
    
    _raus:
        mov  laenge, eax         // Länge in die Variable schreiben
    
        pop  ecx
        pop  ebx
      }
    
      printf("Die Laenge der Zeichenkette: %d \n\n", laenge);
      system("PAUSE");
    
      return 0;
    }
    

    Ciao...



  • jawohl endlich danke leute



  • @KalEl:
    Deine strlen-Funktion ist aber voll die Bremse 🕶



  • Original erstellt von <Alter Mann>:
    @KalEl:
    Deine strlen-Funktion ist aber voll die Bremse 🕶

    Ich weiß net ob die effizientere implementierung so einen Lehrzweck erfüllt, aber viel Spaß damit ^^ (optimiert für intelprozessoren auf 32-bit-basis)

    ;***
    ;strlen - return the length of a null-terminated string
    ;
    ;Purpose:
    ;       Finds the length in bytes of the given string, not including
    ;       the final null character.
    ;
    ;       Algorithm:
    ;       int strlen (const char * str)
    ;       {
    ;           int length = 0;
    ;
    ;           while( *str++ )
    ;                   ++length;
    ;
    ;           return( length );
    ;       }
    ;
    ;Entry:
    ;       const char * str - string whose length is to be computed
    ;
    ;Exit:
    ;       EAX = length of the string "str", exclusive of the final null byte
    ;
    ;Uses:
    ;       EAX, ECX, EDX
    ;
    ;Exceptions:
    ;
    ;*******************************************************************************
    
            CODESEG
    
            public  strlen
    
    strlen  proc
    
            .FPO    ( 0, 1, 0, 0, 0, 0 )
    
    string  equ     [esp + 4]
    
            mov     ecx,string              ; ecx -> string
            test    ecx,3                   ; test if string is aligned on 32 bits
            je      short main_loop
    
    str_misaligned:
            ; simple byte loop until string is aligned
            mov     al,byte ptr [ecx]
            inc     ecx
            test    al,al
            je      short byte_3
            test    ecx,3
            jne     short str_misaligned
    
            add     eax,dword ptr 0         ; 5 byte nop to align label below
    
            align   16                      ; should be redundant
    
    main_loop:
            mov     eax,dword ptr [ecx]     ; read 4 bytes
            mov     edx,7efefeffh
            add     edx,eax
            xor     eax,-1
            xor     eax,edx
            add     ecx,4
            test    eax,81010100h
            je      short main_loop
            ; found zero byte in the loop
            mov     eax,[ecx - 4]
            test    al,al                   ; is it byte 0
            je      short byte_0
            test    ah,ah                   ; is it byte 1
            je      short byte_1
            test    eax,00ff0000h           ; is it byte 2
            je      short byte_2
            test    eax,0ff000000h          ; is it byte 3
            je      short byte_3
            jmp     short main_loop         ; taken if bits 24-30 are clear and bit
                                            ; 31 is set
    
    byte_3:
            lea     eax,[ecx - 1]
            mov     ecx,string
            sub     eax,ecx
            ret
    byte_2:
            lea     eax,[ecx - 2]
            mov     ecx,string
            sub     eax,ecx
            ret
    byte_1:
            lea     eax,[ecx - 3]
            mov     ecx,string
            sub     eax,ecx
            ret
    byte_0:
            lea     eax,[ecx - 4]
            mov     ecx,string
            sub     eax,ecx
            ret
    
    strlen  endp
    
            end
    


  • Moin, Moin...

    @AlterMann:

    Ich hatte auch nicht vor eine super-optimierte Assemblerfunktion zu präsentieren, sondern wollte nur ein Beispiel aufzeigen.

    Aber vielleicht erleuchtest Du mich ja und zeigst mir genau auf, warum meine strlen-Funktion eine Bremse darstellt. Mag sein, dass ich von Deiner unendlichen Weißheit profitieren kann. 😃 😃 😃

    Ciao...



  • @TriPhoenix:
    Wie heist das Programm? Softwarebremse? 😮 Dat bremst ja erst richtig, dann nimm lieber Kai seine func!

    @Kai:
    Zumindest den Len-Zähler hätte man am Ende mit dem Offset subtrhieren können. Bei längeren Strings und vielen strlen macht es sich bemerkbar. Also wenn möglich, immer nur ein Increment pro schleife.



  • Moinsen...

    @Alter Mann:

    Ich falle in tiefer Ehrfurcht vor Deinem Wissen auf die Knie und schäme mich für meine schlichten Kenntnisse im Bereich der Assemblerprogrammierung.

    Die Frage des Themas lautete: Kann mir einer an einem simplen Beispiel zeigen wie man den Inline-Assembler unter VC++ benutzt?

    Es ging also nicht darum, wie man eine optimierte Assemblerroutine programmiert, sondern nur um ein Anschauungsbeispiel!!

    Ciao...



  • Jo kannst wieder aufstehen 😃

    (Wollt doch nur klugschei??en und stänkern) lol



  • Original erstellt von <Alter Mann>:
    **@TriPhoenix:
    Wie heist das Programm? Softwarebremse? 😮 Dat bremst ja erst richtig, dann nimm lieber Kai seine func!
    **

    Das mein lieber alter Mann 😉 kommt aus ner verbreiteten Runtime-Library, das ist net uneffizient, das nutzt die tatsache aus, 4 Byte-Blöcke zu nehmen, was der IA32 nunmal lieber macht als einzelne bytes, denn so kann man die Zahl der Speicherzugriffe senken, und die sinds die die Zeit kosten...

    Deswegen ist die Routine durchaus sehr effizienz..ein Speicherzugriff ist nämlich nunmal immernoch prozessortechnisch sehr lahm 🙂


Anmelden zum Antworten