16bit auf 32bit Variable addieren in Assembler

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • 16bit auf 32bit Variable addieren in Assembler

      Wie erweitere ich die Addition zweier 16bit integer Zahlen auf die Addition einer 16bit Zahl zu einer 32bit long Zahl?

      Ausgangspunkt: 16bit Zahl A zu 16bit-Zahl B addieren und Zahl B überschreiben:

      !LD R16, X+ 'X-Pointer zeigt auf 16bit Variable A (ein Array-Element)
      !LD R17, X+
      !LD R18, Z 'Z-Pointer zeigt auf 16-bit Variable B (ebenfalls Array-element)
      !LD R19, Z+1
      !ADD R16, R18 'Addiere B zu A
      !ADC R17, R19
      !ST Z+, R16 'B wird mit B+A überschrieben
      !ST Z+, R17

      Nach dem !ADC R17, R19 müssten jetzt zwei weitere LD's und ADC's kommen, um das Carry-Bit weiter zu addieren. Es gibt aber wohl keinen ADC immidiate Befehl (wie ADC R16,0).
      Weiss jemand wie man's macht?
    • Also ADC addiert zwei Register mit dem Carry-Bit:

      ADC R17, R19 ==> R17=R17+R19+C

      Zum Addieren/Subtrahieren von Konstanten kannst Du Befehle
      ADDIW .... Addiert ein K zum Word
      SUBIW .... Subtrahiert K von einem Word
      SUBIC ..... Subtrahiert K und C von einem Register

      Word meint in dem Fall Doppelregister und Konstantenverarbeitung geht nur in den Registern 16-31.


      Schreib mal Deinen Pseudocode auf...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Hallo Dennis,
      vielen Dank schon mal.
      das funktioniert bis
      A(1) = 32767
      B(1) = &B11111111_11111111_11111111
      Für B(1)=obiges +1 ergibt sich A+B=32767
      Man muss wohl noch die restlichen zwei Bytes der Long-Variablen B in Register laden und mit addieren, vielleicht so:
      !LD R18, Z
      !LD R19, Z+1 soweit war's wenn B Integer ist, für Long würde das so gehen?
      !LD R20, Z+1
      !LD R21, Z+1
      Aber wie ergänzt man dann in Deinen Code mit zwei weiteren ADCs? Hab's nicht hingekriegt.
    • Wenn Du zwei 16-Bit Werte addierst entsteht maximal ein Übertrag von einem Bit, dem Carry.
      @Dennis hat es ja bereits gelöst.
      Dementsprechend löschen die zwei CLR-Befehle die Register R18+R19, lassen das Carry-Flag aber unberührt. Damit funktioniert der nachfolgende ADC-Befehl und übertragt damit eine "1" in das Register R18 - und R19 bleibt Null.
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Das hatte ich so nicht verstanden, weil oben von 2 16-Bit Variablen A und B die Rede war. Wenn Du eine 16- und 32-Bit Variable addieren willst, dann genügt es die 4 Byte der Longvariable zu laden, z.B. R16-R19 und die 16-Bit Variable z.B. nach R20-R21.

      CLR R22
      ADD R16, R20
      ADC R17, R21
      ADC R18, R22
      ADC R19, R22

      Zurückschreiben musst Du natürlich R16-R19.
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Hallo monkey,
      das tut's aber auch noch nicht.
      Hier der komplette Code, modifiziert gemäß Deinem Vorschlag für 16bit+32bit Variablen
      Hervorgegangen aus einem Beitrag aus dem alten Forum für Integer Array-Addition (am Schluß angefügt).

      Es werden "Cnt" Elemente eines Arrays "src" zu einem Array "trgt" addiert, .

      $regfile = "m328pdef.dat"
      Dim A(20) As Integer , B(30) As Long
      Declare Sub Cmemwcpy(src As Integer , Trgt As Long , Byval Cnt As Word)
      A(1) = 0 '32767 Testwerte
      B(1) = 32767 'b(1)=2147483647
      Cmemwcpy A(1) , B(1) , 1
      Print B(1)
      End
      Sub Cmemwcpy(src As Integer , Trgt As Long , Byval Cnt As Word)
      'http://bascom-forum.de/showthread.php?3322-Beispiel-custom-mem-byte-copy-in-Assembler
      !LD XL, Y
      !LD XH, Y+1
      !Ld R24, X+
      !Ld R25, X
      !LD ZL, Y+2
      !LD ZH, Y+3
      !LD XL, Y+4
      !LD XH, Y+5
      !cpy_start1:
      !SBIW R24, 1
      !BRMI cpy_end1
      !LD R20, X+
      !LD R21, X+
      !LD R16, Z
      !LD R17, Z+1
      !LD R18, Z+1
      !LD R19, Z+1
      !CLR R22
      !ADD R16, R20
      !ADC R17, R21
      !ADC R18, R22
      !ADC R19, R23
      !ST Z+, R16
      !ST Z+, R17
      !ST Z+, R18
      !ST Z+, R19
      !RJMP cpy_start1
      !cpy_end1:
      End Sub

      Der alte Code, funktioniert für Integers:
      Sub Cmemwcpy(src As Integer , Trgt As Integer , Byval Cnt As Word)
      'http://bascom-forum.de/showthread.php?3322-Beispiel-custom-mem-byte-copy-in-Assembler
      !LD XL, Y
      !LD XH, Y+1
      !Ld R24, X+
      !Ld R25, X
      !LD ZL, Y+2
      !LD ZH, Y+3
      !LD XL, Y+4
      !LD XH, Y+5
      !cpy_start1:
      !SBIW R24, 1
      !BRMI cpy_end1
      !LD R16, X+
      !LD R17, X+
      !LD R18, Z
      !LD R19, Z+1
      !ADD R16, R18
      !ADC R17, R19
      !ST Z+, R16
      !ST Z+, R17
      !RJMP cpy_start1
      !cpy_end1:
      End Sub
    • So scheint's zu funktionieren (habe mehrere Grenzwerte ausprobiert):
      (im wesentlichen hatte ich die Z-Pointer-Adressierung nicht verstanden und falsch gemacht)
      Oder sieht jemand noch einen Fehler?
      Dank an alle Helfer.

      Rechnet B(i)=B(i)+A(i), i<=CNT, B long, A int
      Sub Cmemwcpy(src As Integer , Trgt As Long , Byval Cnt As Word)
      !LD XL, Y
      !LD XH, Y+1
      !Ld R24, X+
      !Ld R25, X
      !LD ZL, Y+2
      !LD ZH, Y+3
      !LD XL, Y+4
      !LD XH, Y+5
      !cpy_start1:
      !SBIW R24, 1
      !BRMI cpy_end1
      !LD R16, X+
      !LD R17, X+
      !LD R18, Z
      !LD R19, Z+1
      !LD R20, Z+2
      !LD R21, Z+3
      !ADD R16, R18
      !ADC R17, R19
      !CLR R18
      !ADC R18, R20
      !CLR R19
      !ADC R19, R21
      !ST Z+, R16
      !ST Z+, R17
      !ST Z+, R18
      !ST Z, R19
      !RJMP cpy_start1
      !cpy_end1:
      End Sub
    • Sorry, das hab ich gestern schon wahrgenommen, aber leider nicht berücksichtigt: Wenn Long-Variablen im Spiel sind, dann muss sich der Entwickler um das Vorzeichen kümmern, die CPU tut es nicht.

      Wenn es einen Überlauf gibt, dann kann man den behandeln - muss aber nicht.

      Beispiel:
      B = 2 .147.483.647 als LONG
      C = 2
      A = B + C
      A = 2 .147.483.649 ==>
      = 7F FF FF FF + 02 = 80 00 00 01 = - 2.147.483.647

      Hoffentlich hab ich mich nicht verrechnet...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.