Hallo Forum, mal wieder eine Verständnisfrage. Ich möchte zwei z.B 32 Bit zahlen von einander subtrahieren. Wenn ein Negatives Ergebnis berechnet wird soll dies den gleichen Zahlenwert im positiven haben, sprich aus -231983 soll 231983 werden. Bei eine 8-Bit-Subtraktion mache ich das mit dem Befehel NEG wenn ein Übertrag ins Carry stattgefunden hat. wie ist es bei einer 32-Bit-Zahl. Muß ich nach jeder Teilsubtraktion überprüfen ob ein Übertrag stattgefunden hat und dann den NEG-Befehl ausführen oder nur am Ende der vier Teilsubtraktionen bei einem Carryübertrag dann viermal den NEG-Befehl. Oder soll ich den COM-Befehl nehmen. ich weiß nicht warum, aber ich habe oft ein Ergebnis welches sich um 1 zu einem mit Dezimal und den gleichen Zahlen ausgeführten Rechnung unterscheidet. Danke mal wieder für Eure Hilfe
Was bitte versuchst du da zu machen? Willst du den Absolutwert vom Ergebnis der Subtraktion haben? und soll das Assembler auf einem 8 Bit System sein? Rechnet das mit Einer- oder Zweierkomplement, je nachdem halt COM oder auch nicht. anfänger0815 schrieb: > aber ich habe oft ein Ergebnis > welches sich um 1 mit was für Code? eventuell ein Problem mit der Zweierkomplement Darstellung? > oder nur am Ende der vier Teilsubtraktionen nur am Ende, denn nur dann ist die Zahl negativ geworden. Aber da würde ich eher das Negativ Flag abfragen als das Carry flag, das kann nämlich auch überlaufen wenn du von einer positiven Zahl eine negative abziehst. Wäre halt interessant was für ein System du benutzt und was für Flags das hat.
Große Entschuldigung. Ich arbeite im Moment mit einem Attiny84. Ich verwende Assembler. Genau, ich möchte auf alle Fälle den Betrag einer Subtraktion. Also keine Negativen Werte. Mein Testcode sieht im Moment so aus: ldi tmp10,40 ldi tmp12,30 sub tmp10,tmp12 ldi tmp11,20 ldi tmp12,30 sbc tmp11,tmp12 brcc hp10 neg tmp10 neg tmp11 hp10:
anfänger0815 schrieb: > Muß ich nach jeder > Teilsubtraktion überprüfen ob ein Übertrag stattgefunden hat und dann > den NEG-Befehl ausführen Nein. NEG hilft dir nicht, wenn du es mit mehr als einem Byte zu tun hast. > oder nur am Ende der vier Teilsubtraktionen bei > einem Carryübertrag dann viermal den NEG-Befehl. Nein. NEG hilft dir nicht, wenn du es mit mehr als einem Byte zu tun hast. > Oder soll ich den > COM-Befehl nehmen. Das ist zielführender, reicht aber allein nicht. > ich weiß nicht warum, aber ich habe oft ein Ergebnis > welches sich um 1 zu einem mit Dezimal und den gleichen Zahlen > ausgeführten Rechnung unterscheidet. Nicht ganz. Wenn du COM verwendest, ist das Ergebnis immer um genau 1 daneben(zu klein). Das musst du also einfach nur kompensieren. Beispiel für 16Bit: sub R16,R18 sbc R17,R19 brpl positiv com R16 com R17 subi R16,Low(-1) sbci R17,High(-1) positiv: ...
Super Danke für die schnelle Antwort. Werde ich gleich versuchen nachzuvollziehen.
c-hater schrieb: > Beispiel für 16Bit: > > sub R16,R18 > sbc R17,R19 > brpl positiv Es handelt sich wohl um die Subtraktion 2er unsigned Werte, zumindest deutet darauf hin, dass der TO auf Carry vergleicht. Ergo:
1 | BRSH positiv |
2 | ;; oder |
3 | BRCC positiv |
> com R16 > com R17 > subi R16,Low(-1) > sbci R17,High(-1) Geht kürzer:
1 | neg R17 |
2 | neg R16 |
3 | sbci R17, 0 ; oder sbc R17, Rzero wenn Rzero = 0. |
Und wieder hat der c-hater was vom C-Compiler gelernt :-P Negation für 32 Bits:
1 | com R19 |
2 | com R18 |
3 | com R17 |
4 | neg R16 |
5 | sbci R17, -1 |
6 | sbci R18, -1 |
7 | sbci R19, -1 |
Johann L. schrieb: > Geht kürzer: > > neg R17 > neg R16 > sbci R17, 0 ; oder sbc R17, Rzero wenn Rzero = 0. > > Und wieder hat der c-hater was vom C-Compiler gelernt :-P Das ging mir auch schon oft so. Wenn ich erfahren wollte, ob es für eine bestimmte Rechenoperation einen coolen Assemblertrick gibt, fragte ich einfach den Compiler um Rat und war von seinen Antworten meist positiv überrascht. Irgendwann hat es mir aber gereicht, und ich habe den Compiler angebrüllt: "Wenn du sowieso immer alles besser weißt, dann erledige doch dieses Assemblergefrickel selber, und zwar bitte komplett!" Er war sofort damit einverstanden, und seitdem gebe ich – in einer für uns beide gut verständlichen Sprache – nur noch grob vor, was ich gerne hätte, und der Compiler übernimmt für mich dann netterweise die lästige Assemblerprogrammierung. Und das mit einem Tempo, dass einem die Spucke wegbleibt: Zehntausende Assemblerzeilen in Sekundenschnelle und dabei auch noch fehlerfrei, das muss ihm erst einmal einer nachmachen. Und er meckert nicht einmal, wenn ich von ihm verlange, fast dasselbe Assemblerprogramm mit nur ein paar kleinen Änderungen noch einmal komplett neu zu schreiben.
anfänger0815 schrieb: > Muß ich nach jeder > Teilsubtraktion überprüfen ob ein Übertrag stattgefunden hat und dann > den NEG-Befehl ausführen oder nur am Ende der vier Teilsubtraktionen bei > einem Carryübertrag dann viermal den NEG-Befehl Nee, du mußt mal deinen Rechner "oben" einschalten...wenn du Zahlen subtrahierst (oder addierst) dann machst du das immer mit "Carry" (natürlich nicht bei der niedrigsten Stelle...) und dann kannst du das Ergebnis "verabsolutieren"...was immer dein Assembler dafür an Befehlen bereit stellt. Schau dir mal die vielen Assembler-Beispiele für fundamentale Rechenoperationen an, die es im Netz gibt. Oder schau dir halt an, was dein Compiler aus "abs(sign-32 minus sign-32)" macht. Gruß Rainer
Yalu X. schrieb: > Und das mit einem Tempo, dass einem die Spucke wegbleibt: Zehntausende > Assemblerzeilen in Sekundenschnelle und dabei auch noch fehlerfrei, das > muss ihm erst einmal einer nachmachen. Und wenn mal wieder die Calling-Conventions nicht stimmen, und deshalb das Programm abstürzt ist der Compiler völlig hilflos und fragt dann doch ob sich mal bitte jemand den Assemblercode anschauen kann ;-)
Guest schrieb: > Und wenn mal wieder die Calling-Conventions nicht stimmen, Das ist mir bisher eigentlich nur passiert, wenn ich selber Assemblercode in den Compiler-Output gefrickelt habe. Eigentlich alle Compiler, mit denen ich bisher zu tun hatte, konnten mit ihren eigenen Calling-Conventions zuverlässig umgehen.
Yalu X. schrieb: > "Wenn du sowieso immer alles besser weißt, dann erledige > doch dieses Assemblergefrickel selber, und zwar bitte komplett!" Zu genau dieser Meinung kam ich auch vor 15 Jahren (gcc 3.x / x86). Ich schaffte es nicht mehr, schnelleren Code "per Hand" zu erzeugen. Das mag bei µC noch funktionieren, auf x86 kaum. leo
Guest schrieb: > Yalu X. schrieb: >> Und das mit einem Tempo, dass einem die Spucke wegbleibt: Zehntausende >> Assemblerzeilen in Sekundenschnelle und dabei auch noch fehlerfrei, das >> muss ihm erst einmal einer nachmachen. > > Und wenn mal wieder die Calling-Conventions nicht stimmen, und deshalb > das Programm abstürzt ist der Compiler völlig hilflos und fragt dann > doch ob sich mal bitte jemand den Assemblercode anschauen kann ;-) Wenn man keine Lust hat Assembler selber zu schreiben, muß das ja nicht bedeuten, daß man Assembler nicht mehr lesen kann.
leo schrieb: > Das mag bei µC noch funktionieren, auf x86 kaum. Vor allem dann nicht, wenn sich bestimmte Implementationen in ihrem Verhalten deutlich voneinander unterscheiden. Befehlssequenzen, die auf einem x86 absolut optimal sind, sind auf einem anderen x86 überraschend langsam (z.B. "REP RET").
leo schrieb: > Yalu X. schrieb: >> "Wenn du sowieso immer alles besser weißt, dann erledige >> doch dieses Assemblergefrickel selber, und zwar bitte komplett!" > > Zu genau dieser Meinung kam ich auch vor 15 Jahren (gcc 3.x / x86). Ich > schaffte es nicht mehr, schnelleren Code "per Hand" zu erzeugen. Das mag > bei µC noch funktionieren, auf x86 kaum. > > leo Vor allem kann man sich mit einem Compiler auf einem ganz anderen Niveau unterhalten.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.