-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 17

Thema: Optimierter Programmcode

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    09.07.2007
    Beiträge
    42

    Optimierter Programmcode

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hi,

    ich habe eine Frage an die Programmierer:

    Was macht der (Pre-) / Compiler mit
    " #define BATTERIE (1 << MUX0) | (1 << MUX2) ",
    wenn es irgendwo eingesetzt wird?

    Kommen da (viele) _Shift-left_- und _Or_-
    Maschinenbefehle raus, oder macht er bereits
    OPTIMIERTEN Code draus; ... und verwendet hier
    z.Bsp. "0x03", also gleich das Resultat?

    Danke fürs Aufklären!

    cu Helmut

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    26
    Beiträge
    995
    (1 << MUX0) | (1 << MUX2) und 0x03 ist nicht dasselbe!

    die shft befehle setzen nur den bit 0 und bit 2 und ander bist bleiben wie sie sind, 0x03 setzt jedoch den ganzen port auf 0x03 ohne rücksichtnahme ob er davor bereits eine stellung hatte.

    außerdem schreibt man das so im programmcode:
    port |= BATTERIE;
    port |= (1 << MUX0) | (1 << MUX2); //->Entsteht

    port = 0x03; //das | vorm = fehlt. du seihtst hier wird alles

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    03.07.2007
    Beiträge
    349
    MUX0 setzt das rechteste Bit auf 1, MUX2 das 3. von rechts.
    Die beiden kann man zumindest zusammenfassen, dabei kommt raus:
    0100 | 0001 = 0101 = 5
    Aber auch diese '5' muss mit dem PORT mittels OR verknüpft werden, um eben ein Überschreiben anderer Werte zu vermeiden. Also wird der Compiler wohl nicht viel mehr machen können als wie die rechte Seite, sprich die Konstanten, zusammenzufassen(das hat Superhirn eh schon sehr gut beschrieben).
    Grüße,
    Harri

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    Was macht der (Pre-) / Compiler mit
    " #define BATTERIE (1 << MUX0) | (1 << MUX2) ",
    wenn es irgendwo eingesetzt wird?
    Meinst Du Präprozessor ? Oder das Endprodukt?
    der GCC hat einen schönen Schalter -E , der das Kompilieren abbricht, nachdem der Präprozessor fertig ist, ich habe es ausprobiert:
    Code:
     #define BATTERIE (1<<0)|(1<<2)
     usigned char high;
      high = BATTERIE;
    ein GCC blabla.c -E | grep high ergibt
    Code:
    unsigned char high;
      high = (1<<0)|(1<<2);
    also reinen Textersatz (war auch klar)
    Richtig optimieren tut der Kompiler, ich weiß aber nicht, ob auch bei -O0, da mußt Du selber gucken, dazu habe ich im Moment keine Lust

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Hallo

    Ein kleiner Testcode
    Code:
    #define BATTERIE (1 << MUX0) | (1 << MUX2)
    
    int main(void)
    {
    setLEDs(0);
    ADMUX |= BATTERIE;
    setLEDs(255);
    ADMUX |= 5;
    wird wie folgt übersetzt
    Code:
      29               	.LM2:
      30 0008 80E0      		ldi r24,lo8(0)
      31 000a 0E94 0000 		call setLEDs
      32               	.LM3:
      33 000e 87B1      		in r24,39-0x20
      34 0010 8560      		ori r24,lo8(5)
      35 0012 87B9      		out 39-0x20,r24
      36               	.LM4:
      37 0014 8FEF      		ldi r24,lo8(-1)
      38 0016 0E94 0000 		call setLEDs
      39               	.LM5:
      40 001a 87B1      		in r24,39-0x20
      41 001c 8560      		ori r24,lo8(5)
      42 001e 87B9      		out 39-0x20,r24
      43               	.L2:
    Die setLEDs(); dienen der Orientierung im Assemblerlisting. Schön zu sehen ab LM3/5: Lesen des Ports, Wert verodern, schreiben. Wie man sieht, ist es egal, wie man es formuliert, es ist immer 5.

    Wenn man wirklich nicht weiß, welche Spannungsreferenz und welche Bündigkeit das Ergebniss haben soll, dann weiß man sicher auch nicht, welcher ADC-Kanal zuvor ausgewählt war. Deshalb sollte man die MUX0-4 wenigstens löschen bevor man sie mit |= setzt. Oder man definiert BATTERIE etwas um:

    #define BATTERIE2 (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1 << MUX0) | (1 << MUX2)

    und mit

    ADMUX = BATTERIE2;

    ergibt das dann diesen Code:

    ldi r24,lo8(69)
    out 39-0x20,r24

    Gruß

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    09.07.2007
    Beiträge
    42
    Hallo an alle!

    Zuerst 'mal ein !_ganz_großes_Dankeschön_! für Eure _Spitzen-Abhandlung_!!!!

    Harri hat natürlich recht: 1 + 4 = 5 (nicht 3)
    Sorry war mein Flüchtigkeitsfehler! (... den aber auch Superhirn übersah!)

    Was _ich_ daraus gelernt habe:
    1. der Präprozessor ersetzt einfach nur! (Danke an Sebastian!)
    2. der Compiler ist intelligent*) und macht gleich den richtigen Wert aus einem an sich in Maschinensprache komplexen Ausdruck! (Danke an mic!)
    (Wobei "Maschinensprache" hier im Bsp. nicht so _ganz_ passt; es scheint eher ein Objekt-Code, also die Vorstufe dazu, zu sein.)

    Toll, wie Ihr das erklärt habt: Ich denke, da haben noch jede Menge anderer Leser dazulernen können!

    @mic!
    Die setLEDs(); dienen der Orientierung im Assemblerlisting. ...
    Ist sehr tricki!!!

    Was heißt eigentlich das "lo8(5)" bei einem _Byte_-Register? (Evtl. 'was für den Linker!?)

    Nochmals Danke!
    cu Helmut

    *) denn bei a >>= 4 muss er ja wirklich schieben!
    (Das Gelernte gilt offensichtlich nur bei _Konstanten_!)

    Übrigens meine Idee war, Platz zu sparen; aber da hätte die Lesbarkeit gelitten!

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    *) denn bei a >>= 4 muss er ja wirklich schieben!
    (Das Gelernte gilt offensichtlich nur bei _Konstanten_!)
    Nein GCC ist schlauer als Du denkst
    Er schiebt nicht 4 mal sondern dreht beide nibbles um (swap) und verundet das Ergenbnis mit 0x0F, braucht also nur 2 Takte und keine 4 ...

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  8. #8
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Hallo

    Was heißt eigentlich das "lo8(5)" bei einem _Byte_-Register?
    Ich vermute, es bedeutet "das 8bit-low-byte" einer 16bit-Konstanten beim Schreiben in ein 8bit-Register? Hängt vielleicht mit der Trennung von Code und Daten bei den AVR zusammen - keine Ahnung, was das alles im Detail bedeutet. Das ist die .lst-Ausgabe meines Kompilers. Ich ging bisher davon aus, dies ist der Programmcode in Maschinensprache, so wie er dann vom Assembler in ein .hex gewandelt wird.

    Gruß

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    mit lo8 oder hi8 wird erst richtig klar, wenn man Unsinn programmiert.
    Ich habe so ein Beispiel gerade verwendet:
    Code:
     uint16_t i; 
      uint16_t a = 0x0AED;
      
      while(1) { 
        i = (PINB<<8)|PIND;
        i +=a;
        PORTB = (uint8_t)i;
        PORTC = (uint8_t)(i>>8);
      }
    Ergebnis:
    Code:
     15:bubu.c        ****     i +=a;
      95               	.LM3:
      96 001c 8351      		subi r24,lo8(-(2797))
      97 001e 954F      		sbci r25,hi8(-(2797))
      16:bubu.c        ****     PORTB = (uint8_t)i;
      99               	.LM4:
     100 0020 88BB      		out 56-0x20,r24
      17:bubu.c        ****     PORTC = (uint8_t)(i>>8);
     102               	.LM5:
     103 0022 892F      		mov r24,r25
     104 0024 9927      		clr r25
     105 0026 85BB      		out 53-0x20,r24
    Interessant ist hier vielleicht, daß hier subtrahiert und nicht addiert wird...
    Software is like s e x: its better when its free.
    Linus Torvald

  10. #10
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Interessant ist hier vielleicht, daß hier subtrahiert und nicht addiert wird...
    Weil der Wert negativ dargestellt ist: -(2797) Das sind noch die höheren Weihen des C-Kompilers.

    Ein Blick ins ATMega-Datenblatt zeigt erstaunliches: Es gibt subi-abziehen einer Konstanten und sbci-abziehen einer Konstanten mit carry, aber scheinbar nichts entsprechendes mit add und Konstante!

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •