Multiplikation mit Assembler



  • Hi Leute!

    Ich soll eine Multiplikation mit Assembler erstellen.

    Laut meinem Befehlsblatt funktioniert das ganze so: Wenn ich 16Bit-Zahlen miteinander multplizieren möchte, dann wird der niederwertige Teil in AX und der höherwertige Teil in DX abgelegt. Beispiel: Ich möchte 4 * 35000 rechnen. Die 4 steht in AX und die 35000 steht in BX. Das ergibt ja 140000 in hex 222E0. Dann steht quasi nach der Berechnung 22E0 in AX und 2 in DX, soweit richtig?

    Wenn ich nun aber dieses 222E0 mit 12000, also in hex 2EE0, wieder multplizieren möchte, wie führe ich das dann Code mäßig aus? Ich hab ja jetzt einen Teil der vorherigen Multiplikation in AX und den anderen Teil in DX stehen...

    Das verstehe ich nicht! Könnt ihr mir helfen?



  • Ich kenn auch noch den Befehl mov WORD PTR [VAR1],AX.

    Ich hab jetzt folgenden Code:

    [cpp]
    Daten SEGMENT ; hier beginnt das Segment mit dem Namen DATEN

    Zahl DW 0h
    DIV1 DW 88B8h ; 35000
    DIV2 DW 2EE0h ; 12000
    ERG DW 0h
    VAR1 DD 0h

    ENDS ; hier endet das Datensegment
    ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    CODE SEGMENT
    Anfang:
    mov AX,Daten
    mov DS,AX

    mov AX,4
    mov BX,DIV1
    MUL BX
    mov WORD PTR [VAR1],DX
    mov WORD PTR [VAR1 + 1],AX

    Terminate_Program
    ENDS ; hier endet das Code-Segment
    [cpp]

    Wenn ich mir nun das Datensegemtn dazu anschaue, steht nun ds:0008 02 E0 22. Das korrekt Ergebnis ist aber 02 22 E0. Warum schreibt er mir 22 E0 vertauscht in das Datensegment?



  • Keine Ahnung, Little Endian vs. Big Endian?



  • Gut, auch wenn hier anscheinend das LittleEndian Format benutzt wird, dann stimmts ja trotzdem nicht, oder?

    Wenn ich nun das Wort 02 22 E0 in das DS schreiben möchte, dann würde es ja nach Little Endian so aussehen: E0 22 2. Bei mir im DS steht aber 02 E0 22...

    Heißt das für mich ich muss die Reihenfolge vertauschen in der AX und DX in VAR1 kopiere?



  • So mein neuer Code sieth jetzt so aus:

    mov AX,4
    mov BX,DIV1
    MUL BX
    mov WORD PTR [VAR1],AX
    mov WORD PTR [VAR1 + 2],DX
    

    Wenn ich nun das DS überprüfe steht da jetzt ds:0008 E0 22 02. Das wäre nach LittleEndian jetzt richtig.

    Ich will nun diese neue Produkt, welches ja nun in DS steht mit der Zahl 12000, also in hex 2EE0 multiplizieren. Wie kann ich jetzt den Inhalt von VAR1 mit dem Multiplikanden 2EE0 multiplizieren? Ich kann Rechenoperationen nur mit den Registern ausführen, oder?



  • Hey Leute!

    Könnt ihr mir bei meinem Problem helfen?

    Ich will das Ergebnis der Zahlen 4 * 12000 * 35000 + 131 in Assembler berechnen. Das Ergebnis von 4*12000*35000 hab ich schon korrekt durchführen können. Allerdings macht mir gerade noch die Addition von 131 zu schaffen. Mit dem Befehl clc lösche ich das durch die letzte Multiplikation gesetzte Carry Flag, damit ich ein eventuell durch die nachfolgende Addition entstehendes Carry Flag identifizieren kann welches ja für den Befehl JC benötigt wird, damit mir bei einem evtl. Carry auf das DX Register eins addiert wird. Das komische ist aber, dass, obwohl kein Carry nach der Addition gesetzt ist denn noch auf DX 1 addiert wird. Laut meinen Befehlssatzblättern ist die Syntax für den Befehl JC aber richtig! Hier der Code:

    MOV AX, DATA
    MOV DS, AX
    
    mov AX,0
    mov BX,0
    
    mov AX,4
    mov BX,DIV2
    mul BX
    
    mov BX,DIV1
    mul BX
    
    clc
    
    mov BX,83h
    
    add AX,BX
    JC Carry1
    Carry1:
    add DX,1
    

    Könnt ihr mir helfen?



  • Was soll das Programm machen, wenn das Carryflag nicht gesetzt ist?



  • Das clc entfernt ja das Carryflag welches durch die vorhergehende zweite Multiplikation gekommen ist. Durch die nachfolgende Addition kann ja auch kein Carrykommen und wenn ich das vorhergesetzte nicht wegmache, dann wär ja eins da obwohl die addition gar kein carry liefert. Mein hauptproblem ist eigentlich, warum mir das Programm trotz dem NICHT gesetzen carryflag dx+1 rechnet!



  • Guck mal genau hin. Was tut es denn, wenn das Carryflag nicht gesetzt ist?



  • Welches carry meinst dud enn jetzt? das nach der multiplikation oder das nach der addition?



  • Ich versteh das nicht. Das Programm rennt mir grundsätzlich in dx,1 rein, obwohl ich ja mit jc überprüfe ob ein carry da ist oder nicht. Und er rennt auch rein wenn definitiv kein carry da ist...

    Kannst du mir genau erklären was da faul ist?



  • Das Sprungziel von JC ist der erste Befehl, der gleich nach JC kommt. Somit ist JC wirkungslos.

    Besser wäre vielleicht:

    add AX,BX
    
    ;JC Carry1
    JNC NoCarry1 ; soll add DX,1 überspringen wenn kein Carry
    
    add DX,1
    
    NoCarry1:
    (...)
    


  • Das ist doch auch nicht richtig. Ich will doch dx,1 nur wenn das Carry gesetzt ist...



  • Oder auch nicht dx,1 wenn das Carry nicht gesetzt ist.

    JNC -> Jump if Not Carry



  • Du meinst also, da ich mit clc das carry abgeschaltet überspringt er mit jnc den Befehle add dx,1?

    D.h. wenn ich das carry mit clc nicht weggemacht hätte, dann hätte er den Befehl add dx,1 mit jc übersprungen?



  • (...)
    
    add AX,BX 
    
    JC Carry1 
    
    Carry1: 
    
    add DX,1 
    
    (...)
    

    ^^ So steht es in Deinem Code:

    -> Wenn Carry gesetzt ist, soll das Programm mit dem ersten Befehl hinter Label Carry1 weitermachen.

    -> Wenn Carry nicht gesetzt ist, soll das Programm mit dem ersten Befehl hinter JC weitermachen.

    Aber der erste Befehl in beiden Fällen ist "add DX,1".


Log in to reply