Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter Test

(Siehe auch)
Zeile 180: Zeile 180:
 
Auch diese Beispiele machen nicht viel. Das erste zählt nur eine 16-Bit Variable hoch, das zweite macht nichts weiter, als ein Funktionsaufruf.
 
Auch diese Beispiele machen nicht viel. Das erste zählt nur eine 16-Bit Variable hoch, das zweite macht nichts weiter, als ein Funktionsaufruf.
  
=Eine Variable hochzählen=
+
==Eine Variable hochzählen==
=Eine Funktion aufrufen=
+
 
 +
'''Quellcodes:'''
 +
 
 +
{{Codevergleich|avr-gcc|BASCOM
 +
|
 +
<pre>
 +
int volatile count;
 +
 
 +
SIGNAL (SIG_OVERFLOW0)
 +
{
 +
  count++;
 +
}
 +
</pre>
 +
|
 +
<pre>
 +
</pre>
 +
}}
 +
 
 +
'''Compilat:'''
 +
 
 +
{{Codevergleich|avr-gcc|BASCOM
 +
|
 +
<pre>
 +
__vector_9:
 +
  push __zero_reg__
 +
  push __tmp_reg__
 +
  in __tmp_reg__,__SREG__
 +
  push __tmp_reg__
 +
  clr __zero_reg__
 +
  push r24
 +
  push r25
 +
 
 +
  lds r24,count
 +
  lds r25,(count)+1
 +
  adiw r24,1
 +
  sts (count)+1,r25
 +
  sts count,r24
 +
 
 +
  pop r25
 +
  pop r24
 +
  pop __tmp_reg__
 +
  out __SREG__,__tmp_reg__
 +
  pop __tmp_reg__
 +
  pop __zero_reg__
 +
  reti
 +
</pre>
 +
|
 +
<pre>
 +
</pre>
 +
}}
 +
 
 +
==Eine Funktion aufrufen==
 +
 
 +
'''Quellcodes:'''
 +
{{Codevergleich|avr-gcc|BASCOM
 +
|
 +
<pre>
 +
extern void foo();
 +
 
 +
SIGNAL (SIG_OVERFLOW1)
 +
{
 +
  foo();
 +
}
 +
</pre>
 +
|
 +
<pre>
 +
</pre>
 +
}}
 +
 
 +
 
 +
'''Compilat:'''
 +
 
 +
{{Codevergleich|avr-gcc|BASCOM
 +
|
 +
<pre>
 +
__vector_8:
 +
  push __zero_reg__
 +
  push __tmp_reg__
 +
  in __tmp_reg__,__SREG__
 +
  push __tmp_reg__
 +
  clr __zero_reg__
 +
  push r18
 +
  push r19
 +
  push r20
 +
  push r21
 +
  push r22
 +
  push r23
 +
  push r24
 +
  push r25
 +
  push r26
 +
  push r27
 +
  push r30
 +
  push r31
 +
 
 +
  rcall foo
 +
 
 +
  pop r31
 +
  pop r30
 +
  pop r27
 +
  pop r26
 +
  pop r25
 +
  pop r24
 +
  pop r23
 +
  pop r22
 +
  pop r21
 +
  pop r20
 +
  pop r19
 +
  pop r18
 +
  pop __tmp_reg__
 +
  out __SREG__,__tmp_reg__
 +
  pop __tmp_reg__
 +
  pop __zero_reg__
 +
  reti
 +
</pre>
 +
|
 +
<pre>
 +
</pre>
 +
}}
  
 
=Siehe auch=
 
=Siehe auch=

Version vom 6. April 2006, 13:41 Uhr

Ein wichtiges Merkmal eines Compilers ist die Güte des erzeugten Codes. Immerhin will man seine Hardware optimal nutzen, und die geschriebenen Programme sollen möglichst wenig Laufzeit brauchen und möglichst wenig Speicher – also RAM und Flash – belegen.

Ein Vergleich der erzeugten Codes ist jedoch nicht einfach, denn ein Problem kann bereits innerhalb ein und der selben Programmiersprache auf sehr unterschiedliche Art und Weisen formuliert oder gelöst werden.

Dieser Artikel versucht ansatzweise einen Codevergleich weit verbreiteter AVR-Compiler anhand sehr einfacher Aufgaben.

Ein Vergleich der Programmierung von Hardware-Komponenten und Peripherie wie UART- oder I2C-Module scheint dabei weniger interessant, denn obwohl die Codes zum Steuern dieser Komponente in unterschiedlichen Sprachen recht verschieden aussehen, werden sie doch auf die selben Maschinen-Codes abgebildet, die sich im wesentlichen auf das Setzen und Lesen von Registern (SFRs) reduzieren.

Interessanter erscheint ein Vergleich einfacher Aufgaben, die erkennen lassen, wie gut ein Compiler in der Lage ist, die Ressourcen eines AVR zu nutzen bzw. zu schonen.

Summer der ersten n Zahlen

Berechnet wird die Summe der ersten n Zahlen:

[math] \operatorname{sum}(n) \,=\, \sum_{k=0}^n k \,=\, 1 + 2 + \ldots + n [/math]

Für diese Berechnung gibt es mehrere Möglichkeiten. Die Zahl 'n' wird als 16-Bit Zahl angegeben und das Ergebnis als 16-Bit-Zahl berechnet. Ein eventueller Überlauf wird nicht beachtet.

Der Code wird jeweils als eigene Funktion implementiert, um Abhängigkeiten vom umliegenden Code zu vermeiden.

Aufsummieren in einer Schleife

Quellcodes:

avr-gcc
unsigned int 
sum_n_loop (unsigned int n)
{
   unsigned int sum = 0;
   unsigned int i;

   for (i=n; i > 0; i--)
      sum += i;
	
   return sum;	
}
 
BASCOM

???

Compilat:

avr-gcc
sum_n_loop:
   ldi r18,lo8(0)
   ldi r19,hi8(0)
.L12:
   sbiw r24,0
   breq .L11
   add r18,r24
   adc r19,r25
   sbiw r24,1
   rjmp .L12
.L11:
   movw r24,r18
   ret
 
BASCOM

???


Berechnung mit rekursiver Funktion

Quellcodes:

avr-gcc
unsigned int 
sum_n_rekursiv (unsigned int n)
{
   if (n == 0)
      return 0;

   return n + sum_n_rekursiv (n-1);	
}
 
BASCOM

???

Compilat:

avr-gcc
sum_n_rekursiv:
   push r28
   push r29
   movw r28,r24
   sbiw r24,0
   breq .L13
   sbiw r24,1
   rcall sum_n_rekursiv
   add r24,r28
   adc r25,r29
.L13:
   pop r29
   pop r28
   ret
 
BASCOM

???

Berechnung durch Formel

Quellcodes:

avr-gcc
unsigned int 
sum_n_formel (unsigned int n)
{
   return n*(n+1) / 2;
}
 
BASCOM

???

Compilat:

avr-gcc
sum_n_formel:
   mul r24,r24
   movw r18,r0
   mul r24,r25
   add r19,r0
   mul r25,r24
   add r19,r0
   clr r1
   add r18,r24
   adc r19,r25
   movw r24,r18
   lsr r25
   ror r24
   ret
 
BASCOM

???

Interrupt-Routinen

Auch diese Beispiele machen nicht viel. Das erste zählt nur eine 16-Bit Variable hoch, das zweite macht nichts weiter, als ein Funktionsaufruf.

Eine Variable hochzählen

Quellcodes:

avr-gcc
int volatile count;

SIGNAL (SIG_OVERFLOW0)
{
   count++;
}
 
BASCOM


Compilat:

avr-gcc
__vector_9:
   push __zero_reg__
   push __tmp_reg__
   in __tmp_reg__,__SREG__
   push __tmp_reg__
   clr __zero_reg__
   push r24
   push r25

   lds r24,count
   lds r25,(count)+1
   adiw r24,1
   sts (count)+1,r25
   sts count,r24

   pop r25
   pop r24
   pop __tmp_reg__
   out __SREG__,__tmp_reg__
   pop __tmp_reg__
   pop __zero_reg__
   reti
 
BASCOM


Eine Funktion aufrufen

Quellcodes:

avr-gcc
extern void foo();

SIGNAL (SIG_OVERFLOW1)
{
   foo();
}
 
BASCOM



Compilat:

avr-gcc
__vector_8:
   push __zero_reg__
   push __tmp_reg__
   in __tmp_reg__,__SREG__
   push __tmp_reg__
   clr __zero_reg__
   push r18
   push r19
   push r20
   push r21
   push r22
   push r23
   push r24
   push r25
   push r26
   push r27
   push r30
   push r31

   rcall foo

   pop r31
   pop r30
   pop r27
   pop r26
   pop r25
   pop r24
   pop r23
   pop r22
   pop r21
   pop r20
   pop r19
   pop r18
   pop __tmp_reg__
   out __SREG__,__tmp_reg__
   pop __tmp_reg__
   pop __zero_reg__
   reti
 
BASCOM


Siehe auch


LiFePO4 Speicher Test