loop 512 mal - 16Bit oder 2*9Bit Counter?

OP #2699681
Lesenswert?

Hi,

was ist schneller auf einem ATMega?
1
uint16_t counter=512;
2
do {
3
 irgendwas
4
} while ( --counter);

oder
1
uint8_t count1=2;
2
uint8_t count2=256;
3

4
do {
5
  do {
6
   irgendwas
7
  } while ( --count2);
8
} while ( --count1);

Eigentlich sollte das 2. doch schneller sein, da er hier direkt mit den 
8Bit-Registern arbeiten kann, oder? Ist nur die Frage, ob die zweifache 
Negation und Überprüfung des 2. Registern weniger Zeit in Anspruch nimmt 
als die 16-Bit-Aktionen.

Weiss das jemand?
Gast #2699691
Lesenswert?

Hi

>Eigentlich sollte das 2. doch schneller sein, da er hier direkt mit den
>8Bit-Registern arbeiten kann, oder?

Der ATMega hat auch 16-Bit-Befehle:

 adiw r25:r24,1 incrementiert den Wert in r25:r24

Die Frage ist nur, wie der Compiler das übersetzt. Teste es doch 
einfach. Das Ergebnis siehst du im lss-File.

MfG Spess
Gast #2699700
Lesenswert?

Fehler:
1
uint8_t count2 = 256; // overflow
und den Reset von count2 vergessen:
1
do {
2
do {
3
 //irgendwas
4
} while ( --count2);
5
count2 = 255;
6
} while ( --count1);

Ohne Optimierungen erhalte ich 512 * 8 Instruktionen für die 16-Bit 
Variable und 256  2  5 + 2 * 7 Instruktionen (= 2574) - falls ich mich 
nicht vertan habe. Die Takte habe ich nicht ausgezählt.
OP #2699702
Lesenswert?

Sieht für mich so aus, als ob eine Schleife schneller ist als 2:

1
#define nop()  __asm__ __volatile__ ("nop" ::)
2
void foo()
3
{
4
    uint16_t counter=512;
5
    do 
6
    {
7
        nop();
8
    } while (--counter);
9
}

ergibt:

1
foo:
2
.LFB1:
3
  .loc 1 14 0
4
  .cfi_startproc
5
.L__stack_usage = 0
6
.LVL0:
7
  .loc 1 14 0
8
  ldi r24,lo8(512)
9
  ldi r25,hi8(512)
10
.LVL1:
11
.L2:
12
  .loc 1 18 0 discriminator 1
13
  nop
14
  sbiw r24,1
15
  .loc 1 19 0 discriminator 1
16
  brne .L2
17
  .loc 1 20 0
18
  ret


1
#define nop()  __asm__ __volatile__ ("nop" ::)
2
void foo()
3
{
4
    uint8_t count1=2;
5
    uint8_t count2=255;
6
    
7
    do 
8
    {
9
        do 
10
        {
11
            nop();
12
        } while (count2--);
13
    } while (--count1);
14
}

ergibt:

1
foo:
2
.LFB1:
3
  .file 1 ".././CFile1.c"
4
  .loc 1 14 0
5
  .cfi_startproc
6
.L__stack_usage = 0
7
.LVL0:
8
  .loc 1 14 0
9
  ldi r24,lo8(-1)
10
  .loc 1 15 0
11
  ldi r25,lo8(2)
12
  rjmp .L2
13
.LVL1:
14
.L3:
15
  .loc 1 15 0 is_stmt 0 discriminator 1
16
  subi r24,lo8(-(-1))
17
.LVL2:
18
.L2:
19
  .loc 1 22 0 is_stmt 1 discriminator 1
20
  nop
21
  .loc 1 23 0 discriminator 1
22
  tst r24
23
  brne .L3
24
  .loc 1 24 0
25
  subi r25,lo8(-(-1))
26
.LVL3:
27
  brne .L3
28
  .loc 1 25 0
29
  ret
OP #2700217
Lesenswert?

"C:\Program Files (x86)\Atmel\Atmel Studio 
6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe" 
-funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -g2 
-Wall -Wundef -Werror -pedantic -pedantic-errors -c -std=gnu99 
-save-temps -MD -MP -MF "main.d" -MT"main.d" -MT"main.o" 
-mmcu=atmega1284p   -o"main.o" ".././main.c"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren