MPLAB X IDE : Fehler bei Subtraktion: falsches Flag gesetzt

Begonnen von picass, 02.09.2022, 11:36:38 CEST

⏪ vorheriges - nächstes ⏩

picass

Meine Hoffnung, der in der Version 5.20 entdeckte Rechenfehler könnte in der Version 5.35 – der letzten vor der Umstellung – beseitigt sein, hat sich nicht bestätigt. Der Fehler tritt bei der Subtraktion zweier 8-bit-Zahlen auf, wenn der Wert der Differenz
größer als dez 160 ist und besteht darin, dass das Negativ-Flag gesetzt wird, obwohl das Rechenergebnis ein eindeutig positives ist. Putzigerweise tauchen dann die Flags N und C gleichzeitig als gesetzt, also ,,1" auf, was natürlich nicht sein darf.
Zwei Beispiele:

Minuend Variable bitl  hält h'a8'
Subtrahend Var.   adcl hält h'05'
-----------------------------------------
ergebnis in wreg               h'a3'  , aber N- und C-Flag gleichzeitig gesetzt

Minuend Variable bitl  hält h'a8'
Subtrahend Var.   adcl hält h'a5'
-----------------------------------------
ergebnis in wreg               h'a3'  ,  nur C-Flag korrekt gesetzt

Demnach ist große Vorsicht bei allen Abfragen des N-Flags geboten.
Grüße, lippe1audi

pic18

ich habe mal im C-Compiler nachgeschaut, wie hier ein Vergleich übersetzt wird. Hier wird das Carry Register abgefragt.
uint16_t x, y;
uint8_t ergxy;

172:               if(x>y)
73DA  010A     MOVLB 0xA
73DC  51F5     MOVF iss, W, BANKED
73DE  010A     MOVLB 0xA
73E0  5DF7     SUBWF 0xF7, W, BANKED
73E2  010A     MOVLB 0xA
73E4  51F6     MOVF 0xF6, W, BANKED
73E6  010A     MOVLB 0xA
73E8  59F8     SUBWFB 0xF8, W, BANKED
73EA  E204     BC 0x73F4
173:                   ergxy ='>';
73EC  010A     MOVLB 0xA
73EE  0E3E     MOVLW 0x3E
73F0  6FF9     MOVWF lastport, BANKED
174:               else
73F2  D003     BRA 0x73FA
175:                   ergxy ='<'; //<=
73F4  010A     MOVLB 0xA
73F6  0E3C     MOVLW 0x3C
73F8  6FF9     MOVWF lastport, BANKED

ich weiß nur nicht wo ich die technische Adresse von iss und lastport finde. lastport scheint ergxy zu sein, iss?

pic18

irgendwie ist der Code sehr aufgebläht, es wird ständig MOVLB geladen.
MBLABX IDE v.5.5, C18(v3.47) Compiler

vloki

Das N Bit wird gesetzt, wenn das MSB des Ergebnisses 1 ist.
Das ist so definiert und im demnach auch so in der ALU des PICs festgelegt.
Kann man im Datasheet nachlesen und hat mit der IDE rein gar nichts zu tun.
MPLABX  XC8  KiCAD

picass

Interessant! Allerdings unverständlich. Konnte trotz Suchens keine solche Stelle "im Datasheet" entdecken, und daher fehlt mir eine Begründung, warum dieses Setzten so gewollt ist.
Ist aber auch fast egal, es bestätigt ja meine Aussage, dass das N-Flag bei Subtraktionen nicht, rsp. nur sehr eingeschränkt sinnvoll brauchbar ist, zumindest bezogen auf das Ergebnis. Da hilft in diesen Fällen nur, das N-Flag besser zu ignorieren  und sich stattdessen am C-Flag zu orientieren, das weiß wenigstens zuverlässig, was positiv und was negativ ist.
Grüße, picass

vloki

Guckst du bei STATUS Register ;-)
z.B. beim 18F14K22 -> 3.3.5

ZitatN: Negative bit
This bit is used for signed arithmetic (two's complement). It indicates whether the result was negative
(ALU MSB = 1).
1 = Result was negative
0 = Result was positive
MPLABX  XC8  KiCAD

picass

Danke, habe geguckt! ;)
Echt abgefahren! Das haben sie jetzt von ihrer Trickserei mit der Addition des "two's compliment", statt wie wir anständigen Leute auch "echt" zu subtrahieren, indem man Bit für Bit abarbeitet und "abzieht"! >:(
Das Leben wird schon wieder noch komplizierter! ???
Grüße, picass

vloki

#7
Zitat von: picass am 10.09.2022, 17:40:36 CESTDas haben sie jetzt von ihrer Trickserei...
:)) Wie würdest du denn negative Zahlen binär darstellen.
Für mich war das Zweierkomplement schon immer sehr plausibel.

Das MSB geht halt für das Vorzeichen drauf, wenn auch negative Zahlen vorkommen können
und der maximal sinnvoll verwendbare Wert bei 8-Bit ist eben nur 127 und nicht mehr 255.

Du entscheidest du als Programmierer ja selber.
Wenn du voraussetzt, dass keine negativen Werte vorkommen, dann kannst du mit Werten bis 255 rechnen.
Aber es macht dann nunmal keinen Sinn mehr das N-Bit abzufragen!
MPLABX  XC8  KiCAD

picass

#8
Zitat von: vloki am 14.09.2022, 13:26:04 CEST:)) Wie würdest du denn negative Zahlen binär darstellen.
Das kann ich dir genau sagen: Wenn ich eine solche Zahlendarstellung creieren würde, dann würde ein N-Flag, wobei das N ja für negativ stehen soll, seinem Namen auch voll Rechnung tragen und es würde nur dann, aber auch immer dann gesetzt werden, wenn der Wert einer Differenz "in Echt" negativ wäre. Um ein Rechnen so wie jetzt möglich zu machen, würde ich dann noch ein anderes Flag einführen - Name beliebig -, welches als Hilfs-Flag zuständig wäre.
Als "Verbraucher" sehe ich die Lage einfach: 8-bit ist eine rechte Einschränkung, halt nur 256 Werte verfügbar. Das hat schon Generationen von µC-Nutzern aufgeregt, die 16-Bitter, die 24-Bitter, die 32-Bitter, etc. lassen grüßen . Eine "Rechenmethode" einzuführen, welche diesen niedlichen Zahlenbereich auch noch zweiteilt in einen "sicheren" Bereich und einen, in welchem man mit unsicherem Ausgang rechnen muss, halte ich für eine Zumutung.

Es lebe - wenn auch mit Aufregung - der 8-bit-Microprozessor mit seinem kompletten 8-bit-Zahlenraum. Mit 7-bit-Microprozessoren oder einem solchen Zahlenraum möchte ich nichts zu tun haben. >:(
Ganz ehrlich.
Grüße, picass

vloki

Zitat von: picass am 14.09.2022, 15:34:38 CESTEine "Rechenmethode" einzuführen, welche diesen niedlichen Zahlenbereich auch noch zweiteilt in einen "sicheren" Bereich und einen, in welchem man mit unsicherem Ausgang rechnen muss, halte ich für eine Zumutung.
Die Verantwortung liegt beim Programmierer.
Der muss wissen, was er tut und die passenden Flags als Hilfsmittel heranziehen.

Wenn man das N-Flag abfragt, dann geht man davon aus, dass es negative Zahlen gibt,
somit das MSB nicht mehr für den Zahlenraum zur Verfügung steht und nicht mit Zahlen > 127 gerechnet werden kann.

Die "a8" aus dem Eröffnungspost ist dann ja schon eine negative Zahl (-88).
Wenn man da noch "5" abziehst, kommt "a3" raus (-93). Passt doch ;-)
MPLABX  XC8  KiCAD

picass

Mir gefällt nicht, dass die Verantwortung für diese Krücke dem Programmierer in die Schuhe geschoben wird. Würden - wie von mir dargestellt - zwei Flags verwendet, eines für die wahre Anzeige des negativen Wertes und eines für die technische Handhabung der Subraktionsrechnung im Zweier-Komplement, dann wäre das eine saubere Sache und die Verantwortung läge dort, wo sie hingehört, nämlich beim Ersteller eines Rechensystems, welches keine oder zumindest keine unnötigen Fallgruben bereit hält. Mir muss nicht alles gefallen, schon gar nicht, wenn es unnötig unvollkommen ist. Für mich ist die Logik nicht diejenige, dass man sich einer Krücke anpassen muss, sondern vielmehr, dass es bessere Lösungen ohne Fallen geben sollte.

Einem Sparkassen-Angestellten, welcher mir vermitteln wollte, dass die Mahnung der Überziehung meines Kontos zu Recht bestünde, obwohl von einem Guthaben von 2.500 € nur 250 € entnommen wurden, und der darauf hinweist, dass ihr System nun mal so rechnet, werde ich auch weder "Recht geben" wollen, noch sowas für gut befinden müssen. Das sollte nachvollziehbar sein.
Grüße, picass

picass

#11
Waterloo beim Rechnen !

Habe nach einer Pause die Spur der ,,Rechenkunststücke" in Assembler unter MPLAB X IDE bei Version 5.20 wieder aufgenommen. Da fasst einen nicht nur das Grauen, da ist das Ende des Rechnens mit dem PIC nahe.

Ein voll lustiges Beispiel für User mit Galgenhumor ist angefügt. Da soll in einer schlichten 8-bit-Subtraktion dieses gerechnet werden: dez'1' minus dez'244'. Der PIC kann sich nicht entscheiden, was er vom Ergebnis halten soll, weswegen er gleich gar kein Flag setzt, weder das N für negativ noch das C für positiv. Braucht man das Ergebnis für eine Sprungverzweigung, ist man am Ende, nichts geht mehr. So habe ich feststellen müssen, dass nicht nur das N-Flag gelegentlich nicht gesetzt wird, nix, das triftt auch für das C-Flag zu. Und einen daraus resultierenden ,,echten" Rechenfehler hatte ich auch gefunden.

In einem meiner Programme wird über einen analogen Eingang ein 10-bit-Wert eingesammelt. Der wird dann für die Ausgabe des bis 1.023 reichenden Ergebnisses auf vier Stück 7-segm.-Anzeigen als erstes umgesetzt: vier Variable sammeln die Werte für Tausender, Hunderter, Zehner und Einer ein. Für die Bildung dieser Variablen wird je eine Subtraktion benötigt und darauf folgt eine Verzweigung, je nachdem, ob was Positives oder Negatives rum gekommen ist. Da kann man es nur falsch machen: Setzt man auf das N-Flag, gibt es Fehler, setzt man auf das C-Flag, wird es nicht anders.
Was ein Schrott. Die neueren Versionen nach 5.35 haben eine völlig andere Syntax, sodass man komplett von vorne neu lernen müsste. In diesem Zusammenhang war schon mal von ,,Kultur-Schock" die Rede. Bin mit dem X IDE-Zeug am Ende.
Grüße, picass

Nachtrag:
- das zip-File enthält den kompletten Ordner, welchen das X IDE erzeugt, darunter dann auch das asm-File mit dem Programm.
- das Bild aus seinem Debug-Lauf zeigt das "Unentschieden" nach der Subtraction, der grüne Balken ist die Position des Debuggers.

vloki

#12
Na ja, wenn du schon mit negativen Zahlen rechnest, dann gibt es eben keine .244.
Das ist dann -12! (hatten wir doch weiter oben schon, alles >127 ist dann negativ)

1 -(-12) = 13. Kein Überlauf und nicht negativ. Passt alles.

Verwende (lerne) irgendeine Hochsprache, dann musst du dich mit den Details nicht mehr plagen ;-)
MPLABX  XC8  KiCAD

picass

Zitat von: vloki am 30.09.2022, 09:36:55 CESTPasst alles.
Nichts passt, siehe nachfolgendes Beispiel.
Die Croux beginnt bei so was scheinbar Simplem wie einer 16-bit-Subtraktion. Wenn der Subtrahend größer ist als der Minuend, was ja nun wirklich nicht als ,,Spezial-Fall" deklariert werden sollte, dann muss ein Übertrag erfolgen, rsp. dem Subtrahend eine ,,Eins" abgezogen werden. Dafür braucht es ein Flag. Zwei stehen zur Verfügung und beide sind unzuverlässig. Ende der Erklärung und dafür die Bankrott-Erklärung der Subtraktion beim PIC unter den genannten Bedingungen – Assembl. und X IDE. Da sollte man nicht drum rum reden und da helfen auch keine Grundrechen-Beispiele, die keinen Bezug zur Realität dieser Problematik haben.

Wenn an einem analogen Eingang tatsächlich die Werte von 0 bis max. 10 bit vorkommen, dann kann nicht ernsthaft erwartet werden, dass man diesen Wertebereich in 8-bit-Dekaden zerlegt und die dann nochmal in zwei 128-bit-Bereiche und die Eingangswerte auf die entsprechenden Zugehörigkeiten abklopft. Das ist einfach Murks, wenn die Programmiersprache da kein verlässliches Arbeiten zulässt und dieser Murks sollte auch als Murks benannt werden.

Jetzt verstehe ich im Nachhinein auch, warum ich beim Ausbaldowern solcher Prog-Beispiele anderer Autoren ins Stolpern und Grübeln kam, warum das manchmal einfach nicht klappen wollte. Auch die weiter oben genannten beiden promovierten Autoren, die beiden Könige, sind in diese Falle getappt, ohne auch nur im Ansatz dieses Problem genannt und noch viel weniger, einen Ausweg aufgezeigt zu haben. Es war mir früher schon aufgefallen, dass deren Beispiele zu Rechenfehlern führten, ohne allerdings die Ursache gekannt zu haben.

Da bin ich nun echt ratlos, wie es weiter gehen soll, wenn niemand in der Lage ist, eine praktisch umzusetzende Hilfe zu geben. Das Assemblern möchte ich ungerne aufgeben. Es gibt Programme, die in diversen Steuerungen laufen und für die einfach Service in dieser Sprache bereit stehen muss.
Eine Frage wäre es, ob in den neueren Versionen der MPLAB-Umgebung dieses Prob beseitigt wäre.
Grüße, picass

picass

Schade, die Nachbearbeitungszeit war schon rum.

Kann sein, dass ich mich wie weiland Münchhausen gerade am eigenen Haarschopf aus dem Sumpf ziehe, denn ich habe gerade in die PIC-Bibel geschaut, also in das Datenblatt. Und da gibt es sowas wie die "compare"-Befehle. Die benötigen selbst kein Flag und erzeugen auch keines. Wenn die gleich stattfindenden Test das verifizieren sollten, was da versprochen wird, dann wäre das die Lösung.
Grüße, picass

Schnellantwort

Name:
Verifizierung:
Bitte lassen Sie dieses Feld leer:

2 Beeren und 2 Bananen. Welche Farbe hat die Banane ?:
Tastenkürzel: Alt+S Beitrag schreiben oder Alt+P für Vorschau