Forum: Compiler & IDEs Bug in microchip/xc8/v2.20/pic/sources/c90/common/awdiv.c?


von Rudi R. (microwitsch)


Lesenswert?

1
25:                while((divisor & 0x8000U) == 0) {
2
07C8  1BF1     BTFSC n, 0x7
3
07C9  2FD4     GOTO 0x7D4
4
07D3  2FC8     GOTO 0x7C8

mit Dissasambling habe ich hier diese Stelle in XC8 2.20/ C90 awdiv.c 
gefunden, die ja zu einer Endlosschleife führen würde, wenn Bit7= 0 
ist!??

Und dann weiß ich als C-Neuling noch nicht, was 0x8000U bedeuten 
soll?Was bedeutet das U am Ende des Literals??

Ich arbeite gerade an einer Programmanalyse, die mir helfen sollte 
C-Code mit Gegenüberstellung von Assemlercode für mich begreifbarer zu 
machen.Also meine Praxis gleich an Mikrocontrollern, statt wie in meinem 
Buch mit Getränkeautomaten.
Letztlich brauche ich C für Mikros, deshalb hoffe ich in der Hinsicht 
lehrmäßig abkürzen zu können.

Danke schon mal,hier wurde mir ja schon einige Male weiter 
geholfen...eine super Anlaufstelle hier!

Gruß André :)

[Edit: code-Tags eingefügt. – Mod.]

: Bearbeitet durch Moderator
von Harald K. (kirnbichler)


Lesenswert?

Rudi R. schrieb:
> Und dann weiß ich als C-Neuling noch nicht, was 0x8000U bedeuten
> soll?Was bedeutet das U am Ende des Literals??

Steht in Deinem C-Buch. U wie unsigned.

von Oliver S. (oliverso)


Lesenswert?

Rudi R. schrieb:
> 125:                while((divisor & 0x8000U) == 0) {
> 207C8  1BF1     BTFSC n, 0x7
> 307C9  2FD4     GOTO 0x7D4
> 407D3  2FC8     GOTO 0x7C8
>
> mit Dissasambling habe ich hier diese Stelle in XC8 2.20/ C90 awdiv.c
> gefunden, die ja zu einer Endlosschleife führen würde, wenn Bit7= 0
> ist!??

Nein, tut es nicht.
„BTFSC  Übergehe nachfolgenden Befehl, wenn Bit=0  (bit test f, skip if 
clear)“

Vermutlich ist es wenig hilfreich, C-Code u. Assembler zu vergleichen, 
wenn man beides nicht kann. Lern erst eins von beiden, oder leg dir 
zumindest ein Assembler-Befehlsverzeichnis zum Nachschlagen zu.

Oliver

von Oliver S. (oliverso)


Lesenswert?

Oliver S. schrieb:
> Nein, tut es nicht.

Ok, das nehme ich zurück. 207C8 soll wohl 0x7C8 bedeuten.

Da müsstest du dann doch mal etwas mehr vom C-Code zeigen, um zu 
erkennen, was da eigentlich gewollt ist.

Oliver

von Volker S. (vloki)


Lesenswert?

Oliver S. schrieb:
> Ok, das nehme ich zurück. 207C8 soll wohl 0x7C8 bedeuten.

Passt schon. 0x7C8 ist eine Adresse im Programmspeicher.
Wenn mit BTFSC ein Befehl (der an 0x7C9) übersprungen wird,
kommt man dadurch nicht nach 0x7D3 -> keine Endlosschleife!

von Oliver S. (oliverso)


Lesenswert?

Volker S. schrieb:
> Wenn mit BTFSC ein Befehl (der an 0x7C9) übersprungen wird,
> kommt man dadurch nicht nach 0x7D3 -> keine Endlosschleife!

Natürlich.

Jetzt bleibt nur die offene Frage, die sich wohl auch der TO gestellt 
hat, wer oder was da Bit 7 setzen sollte, wenn es ursprünglich nicht 
gesetzt war. Denn ohne das ist das tatsächlich eine  Endlosschleife.

Dazu müsste man mal das ganze C-Programm sehen.

Oliver

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Oliver S. schrieb:
> bleibt nur die offene Frage

... und was von 0x7CA bis 0x7D2 alles so passiert ...

LG, Sebastian

von Volker S. (vloki)


Lesenswert?

Oliver S. schrieb:
> Dazu müsste man mal das ganze C-Programm sehen.
1
// integer signed division
2
3
signed int
4
#ifdef __PICC__
5
__awdiv(signed int divisor, signed int dividend)
6
#else
7
__awdiv(signed int dividend, signed int divisor)
8
#endif
9
{
10
  signed int  quotient;
11
  unsigned char  counter, sign;
12
13
  sign = 0;
14
  if(divisor < 0) {
15
    divisor = -divisor;
16
    sign = 1;
17
  }
18
  if(dividend < 0) {
19
    dividend = -dividend;
20
    sign ^= 1;
21
  }
22
  quotient = 0;
23
  if(divisor != 0) {
24
    counter = 1;
25
    while(((unsigned int)divisor & 0x8000U) == 0) {
26
      divisor <<= 1;
27
      counter++;
28
    }
29
    do {
30
      quotient <<= 1;
31
      if((unsigned int)divisor <= (unsigned int)dividend) {
32
        dividend -= divisor;
33
        quotient |= 1;
34
      }
35
      *(unsigned int *)&divisor >>= 1;
36
    } while(--counter != 0);
37
  }
38
  if(sign)
39
    quotient = -quotient;
40
  return quotient;
41
}

von Harald K. (kirnbichler)


Lesenswert?

Wenn das mit Optimierung übersetzt wird, ist der Bezug zwischen 
einzelnen Assemblersequenzen und dem C-Quellcode praktisch nicht mehr 
vorhanden; es ist also nicht ansatzweise klar, ob das vorher gezeigte 
Codeschnipsel irgendwas mit der dort als Kommentar enthaltenen 
Quelltextzeile zu tun hat.

Eine 1:1-Abbildung gibt es nur bei Übersetzung ohne jedwede Optimierung.

von Oliver S. (oliverso)


Lesenswert?

Harald K. schrieb:
> es ist also nicht ansatzweise klar, ob das vorher gezeigte
> Codeschnipsel irgendwas mit der dort als Kommentar enthaltenen
> Quelltextzeile zu tun hat.

Es ist zumindest nach dran, und das Problem mit der Endlosschleife ist 
nun mal im Assemblercode vorhanden.

Aber ja, man müsste auch den ganzen Assemblercode sehen.

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Es ist zumindest nach dran, und das Problem mit der Endlosschleife ist
> nun mal im Assemblercode vorhanden.

Wenn du dir den C-Code ansiehst, solltest du erkennen können, dass die 
nicht endlos laufen kann. Die Schleife wird nur betreten, wenn der 
Divisor nicht 0 ist. Dann hat er also schon einmal mindestens ein Bit 
gesetzt. Dann wird in der Schleife so lange nach links geschoben, bis 
das höchstwertige gesetzte Bit in Bitposition 15 auftaucht. An dieser 
Stelle bricht sie ab.

von Oliver S. (oliverso)


Lesenswert?

Jörg W. schrieb:
> Dann wird in der Schleife so lange nach links geschoben, bis
> das höchstwertige gesetzte Bit in Bitposition 15 auftaucht. An dieser
> Stelle bricht sie ab.

Ja, das steht im C-Code.

Nur steht trotzdem im Assemblercode eine Schleife, die, falls das MSB im 
Register n nicht gesetzt ist, zur Endlosschleife wird. Jetzt kann es ja 
durchaus sein, daß der Fall "MSB nicht gesetzt" da vorher abgefangen 
wird, was dann allerdings den gezeigten Code ad absurdum führt, da 
nutzlos. Dafür müsste man halt den ganzen Code sehen.

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Jetzt kann es ja durchaus sein, daß der Fall "MSB nicht gesetzt" da
> vorher abgefangen wird

Genau so ist es, das wird vorher abgefangen.

> was dann allerdings den gezeigten Code ad absurdum führt, da nutzlos

Der gezeigte Code sind doch nur aus dem Ganzen heraus geschnipselte 
Teile, wie man anhand der Adressen sehen kann. Die weggeschnittenen 
Teile werden dann schon dafür zuständig sein, die im C-Code zu sehende 
Bitschubserei zu erledigen.

von Rudi R. (microwitsch)


Lesenswert?

Oh,hier ist viel passiert...und ich habe natürlich zwischendurch weiter 
gegrübelt und mein Programmzeug dazu klären 
können!...Reverse-"Ingenieering" ist schon eine lustige Sache!...aber 
mir sollte es hier nur helfen beide Code zu verstehen bzw. 
nachvollziehen zu können.Es werden definitiv beim Dissass zu viele 
Zwischen-Speicherungen gemacht, die man nachher im Code weglassen 
kann!Dienen wohl etwas zur Verwirrung, weil man ja die Optimierungen 
käuflich erwerben soll denke ich mal....Aber Assemler ist nach wie vor 
cool muss ich sagen, wenn man Fehler aufspüren will...erscheinen mir die 
Assembler-coder immer viel plausibler, nachvollziehbarer.Nichts desto 
Trotz ist C nachtürlich schneller zu schreiben und ein Unding, wenn man 
C nicht nutzen wollen würde.:o)...das wurde mir dann schnell bei diesem 
Beispiel hier auch klar!Habe jetzt aber beide Versionen davon...also mit 
Picas und mit XC8...nun kann ich mir das mal in Ruhe angucken und 
gegenüberstellen?Ich bin doch bestimmt nicht der Erste, der das so macht 
oder??:)

Danke für eure Beteiligung, also hier kann man schon was Fragen, hier 
gibts dann genügend die Ahnung haben!Das ist immer gut zu wissen.

von Rudi R. (microwitsch)


Angehängte Dateien:

Lesenswert?

Hier habe ich mal das Projekt angehangen.(Linux Mplap X IDE v5.40 mit 
Pic-as (V2.30))Es ist nicht aufgeräumt, muss ich mal ran.

Ich hatte nun aus dem Disass alles in LimbreOffice-Calc copiert und dann 
was ich für die Picas-Datei (.s) brauchte dann wieder rübercopiert.

Die "mainDissasFromMV.s" ist die Datei, die man includen muss und dann 
hat man die Assembler-Version, die ich aber noch nicht komplett 
überprüft habe!

Vielleicht mache ich das mal in der Simulation, weil ich den Controller 
nicht habe.Werde das mal versuchen für einen universelleren PIC wie 
meinen 16F18877 umzuschreiben, da lerne ich gleich wieder mit der Doku 
davon umzugehen.

Also vielleicht ist das gerade für welche, die doch mal mit den 
Pic-as-Compiler was probieren wollen und Einsteiger sind ganz hilfreich?
2925 Codezeilen sind mit der Navigation in Mplab eigentlich noch gut 
überschaubar.

Hier dazu dann auch noch das Orginal von der Seite " Simple Circuit", es 
ist eine Realtime-clock mit Alarm und Thermometer.Das Beispiel gefiel 
mir ganz gut,um mal Menue-Führungen zu studieren."Button-debounce" war 
für mich ebenfalls interessant, scheint eine Taster-Entprellung zu sein, 
werde ich auch für einen anderen Code gebrauchen 
können.[[https://simple-circuit.com/mplab-xc8-ds3231-alarm-temperature/]]

von Peter D. (peda)


Lesenswert?

Rudi R. schrieb:
> 25:                while((divisor & 0x8000U) == 0) {
> 07C8  1BF1     BTFSC n, 0x7
> 07C9  2FD4     GOTO 0x7D4
> 07D3  2FC8     GOTO 0x7C8

Nicht Dein Ernst?
Du unterschlägst Code und behauptest dann frech, das wäre ein 
Compilerbug.
Was passiert in den Zeilen 07CA..07D2?
In einer Schleife muß immer irgendwo ein Rücksprung stehen, nur eben 
nicht direkt nach dem Testbefehl wieder zum Test.

: Bearbeitet durch User
von Rudi R. (microwitsch)


Lesenswert?

Peter D. schrieb:
> Du unterschlägst Code und behauptest dann frech, das wäre ein
> Compilerbug.

Die zweite Frage war ja das mit "0x8000U"...wusste noch nicht was das 
"U"aussagen sollte...dadurch war der Rest für mich auch noch nicht so 
plausibel!?

Ich hatte mich gefragt,ob es ein Bug oder Falschmeldung sein sollte?
Aber hatte sich ja nun geklärt...
Deshalb hatte ich hier auch die Quelle" awdiv.c" in der Frage angegeben, 
damit jeder,der Mplab nutz, bei sich die Datei hätte aufrufen 
können...Ich meinte dass es reichen würde  aber muss ich dann wohl beim 
nächstem Mal die komplette Datei anhängen.

Was beim Disass doof ist, das alle Variablen zwischendurch wieder anders 
verwendet werden und man dann wirklich genau gucken muss, was gemeint 
ist...aber ist wohl eine Gewönungsfrage und wohl auch nix für Anfänger, 
die da erst einmal durchsehen müssen.

Ich denke mal wer C beherrscht, dem wird Disass nur noch selten 
interessieren, weil das meiste ja wohl doch hinzuhauen scheint, was der 
Compiler da zaubert.

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
Noch kein Account? Hier anmelden.