Bloody Beginner in ASM hat ne Frage *g*



  • Hi.
    Also ich habe noch nie nie nie was gemacht mit ASM.
    Wenn ich das richtig verstanden habe kann man aber ASM Code auch mit dem Programm Compilieren, was man für C/C++ verwendet.
    Ich nutze MS Developer Studio 97 (Version 5.0)

    Wie muss ich das nun machen wenn ich ein Programm schreiben will wo ich eine Zahl x eingebe und er sie mir mit 5 quaddriert?

    Danke für eure Hilfe.



  • Hi.

    Hab leider keine Ahnung, wie die Syntax fuer den Inline-Asm bei deinem Compiler aussieht, aber AFAIK kanns nur "asm", "_asm" oder "__asm" sein.

    Ich nehme an, Du meintest mit "mit 5 quadrieren", "mit 5 potenzieren"?

    Dann koennte der code zB. so aussehen:

    long Var1;
    
    int main(){
      cin >> Var1;
        __asm{
            mov ecx,4
            mov eax,Var1
            mov ebx,eax
    Loop0:
            imul ebx  //eax=eax*ebx
            loop Loop0  //4* (steht in ecx) wiederholen
            mov Var1,eax
    
        };
        cout << "^5: " << Var1 << endl;
        return 0;
    
    };
    

    Das ganze funktioniert natuerlich nur mit kleineren Werten, sonst gibts nen Ueberlauf und es kommt nur Quark raus. 😉



  • Ja okay habs getestet und funzt auch nice.
    aber was passiert da eigentlich? *g*



  • OK, ich versuch mal, mich verstaendlich auszudruecken *fg* 😉

    Also mal alles der Reihe nach betrachten...
    Zuerstmal benutzt man in ASM zum Rechnen die Prozessor-Register.
    In diesem Beispiel werden eax, ebx, ecx und edx verwendet (wobei von edx im Code nichts zu sehen ist 😉 )
    Diese Register verhalten sich praktisch wie normale 32Bit-Variablen, mit dem Unterschied, dass sie nicht im Speicher liegen.

    Weiter:
    Ueblicherweise wird der Asm code - wie normaler C/C++-Code auch von oben nach unten abgearbeitet...

    Also zuerst
    "mov ecx,4"
    Die "mov"-Instruktion kopiert den links nach dem Komma stehenden Wert in das vor dem Komma angegebene Ziel.
    Das Ziel (links) kann ein Register oder eine Stelle im Speicher sein.
    Die Quelle (rechts) kann entweder eine feste Zahl, eine Stelle im Speicher oder ein Register sein.
    Folgende Kombinationen sind Moeglich:
    Register<=Zahl
    Register<=Speicher
    Register<=Register
    Speicher<=Zahl
    Speicher<=Register
    (Speicher<=Speicher geht nicht!)

    Hier wird demnach also die Zahl 4 in das Register "ecx" geschrieben.

    Die Folgenden Zeilen erklaeren sich dann von selbst:
    "mov eax,Var1"
    Der Wert aus dem Speicherbereich, der in diesem Programm mit "Var1" betitelt ist, wird in das Register "eax" kopiert.

    "mov ebx,eax"
    Das Register eax wird in das Register ebx kopiert.

    "Loop0:"
    Das hier ist kein OpCode, sondern eine Sprungmarke - ein Label...

    "imul ebx"
    Diese Instruktion fuehrt eine Integer-Multiplikation mit eax und dem im Operanden stehenden Wert durch. (in diesem Fall ebx) Das Ergebnis wird in eax und edx abgelegt. (in eax sind die unteren 32Bit des Ergebnisses; in edx die oberen => das Ergebnis ist eigentlich 64Bit lang)
    Der Operant dieser Instruktion kann hier ein Register oder eine Speicherstelle sein. Feste Zahlen gehen leider nicht.

    "loop Loop0"
    Diese Instruktion dekrementiert erstmal das Register ecx um 1. Ist ecx<>0, wird zu dem im Operanden angegebenen Label gesprungen (hier Loop0) und der Code von dort aus weiter ausgefuehrt, sonst gehts einfach hinter loop weiter mit der naechsten Instruktion.

    "mov Var1,eax"
    eax wird in die Var1 zurueckgeschrieben.

    Das wars schon... Schau dir auch mal einige der OpCode-Listen und Tuts in der FAQ an. 🙂



  • Hallo!
    Estmal vielen dank für die gute erklärung. ist sogar verständlich.
    Ich habe allerdings noch ein paar fragen:

    :: Was bedeutet dieser Ausdruck: ecx<>0
    :: Was hat es damit auf sich: in eax sind die unteren 32Bit des Ergebnisses; in edx die oberen. Wie muss man sich das vorstellen und warum wird das so gemacht. Kann man daraus einen nutzen ziehen oder macht es das ganze für den Programmierer nur umständlich?



  • zu1:
    "<>" ist ungleich. Eben "<" oder ">", aber nicht "=" 😉 (Wird in Pascal und Basic verwendet... Ich finds schoen 🙂 )

    zu2:
    Wenn Du 2 32Bit-Werte miteinander multiplizierst, ist denke ich einleuchtend, dass sehr schnell ein 32Bit-Wert nicht mehr ausreicht, um das Ergebnis darzustellen. (Zahlen werden zu gross)
    Daher muss ein 64Bit-Wert fuer das Ergebnis her. Da der Pentium keine fuer Rechnungen zur Verfuegung stehenden 64Bit-Register hat (irgendwelche Erweiterungen, wie MMX und den Coprozessor mal ausgenommen - das sind hier schliesslich x86-Befehle), wird dieser 64Bit-Wert einfach auf 2 32Bit-Register verteilt:

    Ergebnis d. Multiplikation:
    BitNr.
    0 ... 31 32 ... 63
    |__eax_| |__edx__|
    

    Bei 16Bit Multiplikationen wird das Ergebnis genauso auf ax und dx verteilt...


Anmelden zum Antworten