Forum: Mikrocontroller und Digitale Elektronik warum schreibt der C-Compiler diese Codeteile?


von Michael D. (etzen_michi)


Lesenswert?

Nabend.

Ich habe mir mal Interessehalber bei einem Programm den Code angeschaut 
und so einige Stellen gefunden bei denen ich mir unsicher bin oder nicht 
verstehe was diese bezwecken sollen:

-Sehe ich das richtig das er hier dauerhaft den Befehl "sei" ausführt?:
1
sei();
2
  c4:  78 94         sei
3
  c6:  ff cf         rjmp  .-2        ; 0xc6 <main+0x58>
1
int main() {
2
   sei();
3
   while(1) {
4
   };
5
}


- Warum wird hier ein eor auf das gleiche Register durchgeführt?
- Warum Multipliziert er hier mit einem Wert obwohl R19 nur 0 sein kann?
- Warum addiert er hier r0, wird dieses nicht für den Wert 0x00 
verwendet?
- Hier macht er schonwieder ein XOR mit den gleichen Registern.

[avrasm]
PORTB= (PORTC&0b11111100) | (Zahl[aktSeg/2][Nummer]&0b00000011);
  c8:  45 b3         in  r20, 0x15  ; 21
  ca:  20 91 e4 00   lds  r18, 0x00E4
> ce:  99 27         eor  r25, r25
  d0:  87 fd         sbrc  r24, 7
  d2:  90 95         com  r25
  d4:  26 95         lsr  r18
- d6:  30 e0         ldi  r19, 0x00  ; 0
  d8:  a0 e6         ldi  r26, 0x60  ; 96
  da:  b0 e0         ldi  r27, 0x00  ; 0
  dc:  6c e1         ldi  r22, 0x1C  ; 28
  de:  70 e0         ldi  r23, 0x00  ; 0
  e0:  26 9f         mul  r18, r22
  e2:  f0 01         movw  r30, r0
  e4:  27 9f         mul  r18, r23
  e6:  f0 0d         add  r31, r0
> e8:  36 9f         mul  r19, r22
> ea:  f0 0d         add  r31, r0
> ec:  11 24         eor  r1, r1
  ee:  e8 0f         add  r30, r24
  f0:  f9 1f         adc  r31, r25
  f2:  ea 0f         add  r30, r26
  f4:  fb 1f         adc  r31, r27
  f6:  20 81         ld  r18, Z
  f8:  23 70         andi  r18, 0x03  ; 3
  fa:  4c 7f         andi  r20, 0xFC  ; 252
  fc:  24 2b         or  r18, r20
  fe:  28 bb         out  0x18, r18  ; 24
/avrasm]
1
void Ziffer(int8_t Nummer) {
2
     PORTB= (PORTC&0b11111100) | (Zahl[aktSeg/2][Nummer]&0b00000011);
3
     PORTD= (PORTD&0b00000011) | (Zahl[aktSeg/2][Nummer]&0b11111100);
4
}

Ich nutze AVRStudio v4.18 mit der Optimierungsoption Qs.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Michael D. schrieb:
> -Sehe ich das richtig das er hier dauerhaft den Befehl "sei" ausführt?:

Nein, der Program-Counter steht nach Einlesen des RJMP-OPcodes schon 2 
Bytes weiter. Deshalb steht da -2. D.h. der µC tritt erst nach dem 
sei() auf der Stelle.

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Man sollte schon Assembler können, um Assemblercode nachvollziehen zu 
können.
Und die Sprache vom Compiler zu lernen ist nicht der glücklichste Weg...

von Dussel (Gast)


Lesenswert?

>- Warum wird hier ein eor auf das gleiche Register durchgeführt?
Das ist eine von vier Möglichkeiten, ein Register auf 0 zu setzen. Warum 
er dazu eor nimmt, weiß ich nicht. Vielleicht kann das als Einziges auf 
alle Register angewendet werden.

>- Warum addiert er hier r0, wird dieses nicht für den Wert 0x00
>verwendet?
Du hast den Assemblercode. Guck nach, was drin steht.

von Frank K. (fchk)


Lesenswert?

Michael D. schrieb:

> -Sehe ich das richtig das er hier dauerhaft den Befehl "sei" ausführt?:

Der PC steht nach der Decodierung des rjmp auf dem nachfolgenden Befehl. 
rjmp ist 2 Bytes lang. rjmp .-2 springt also immer wieder auf sich 
selbst.

>
> - Warum wird hier ein eor auf das gleiche Register durchgeführt?
x^x=0 -> opcodemäßig die kürzeste Art, 0 in ein Register zu laden.

> - Warum Multipliziert er hier mit einem Wert obwohl R19 nur 0 sein kann?
weil Du den gcc verwendest und der nicht für 8 Bit Prozessoren 
entwickelt wurde, und weil gemäß C-Standard Array-Indizes vom Typ int 
sind.
> - Warum addiert er hier r0, wird dieses nicht für den Wert 0x00
> verwendet?
nein, r0 ist ein ganz normales Register, wie die anderen 31 auch.
> - Hier macht er schonwieder ein XOR mit den gleichen Registern.
Siehe oben.

PS: eventuell ist es effizienter, wenn Du auf dem zweidimensionalen 
Array ein eindimensionales machst und/oder die erste Dimension eine 
Zweierpotenz ist. Letzteres erspart die Multiplikation.

von Dussel (Gast)


Lesenswert?

Noch ein Nachtrag: clr rx ist genau das Gleiche wie eor rx,rx.

von spess53 (Gast)


Lesenswert?

Hi

>Hier macht er schonwieder ein XOR mit den gleichen Registern.

Wie schon gesagt setzt er das Register auf 0. In Assembler gibt es dafür 
noch den Befehl 'clr rxy'. Der Op-Code ist aber identisch mit 'eor 
rxy,rxy'. Deshalb übersetzt der Disassembler das mit eor.

MfG Spess

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Michael D. schrieb:

> sei();
>   c4:  78 94         sei
>   c6:  ff cf         rjmp  .-2        ; 0xc6 <main+0x58>

RJMP codiert die Adresse relativ, daher das .-2

In Kommentaren steht die absolute Adresse (0xc6)

Für besseres Verständnis kann man den Assembler-Code anschauen (zB 
-save-temps -fverbose-asm) anstatt ein Disassebly wie hier.

von Michael D. (etzen_michi)


Lesenswert?

Vielen Dank für die Infos.

Werde mal nachdenken ob ich das mit dem Array nochmal umänder.

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.