Array aus Unions - geht das?

Gast #616095
Lesenswert?

Kann ich in C ein Array von Unions anlegen und wie greife ich darauf zu?

Ich hab es so probiert:

typedef union
{
  uint16_t i16;
  struct
  {
    uint8_t l;
    uint8_t h;
  }i8;
} un_i16;


volatile un_i16 ust1_data[30];

folgender Zugriffsveruch klappt nicht:

  SSP1BUF=ust1_data.i8.h[3];

Was tun?
Gast #616110
Lesenswert?

die klammern brauchst du nicht:
1
SSP1BUF = ust1_data[3].i8.h;
übrigens ist das keine gute idee, auf die beiden bytes eine 16-bit 
wertes zuzugreifen.
besser:
1
uint16_t x = 0x1234;
2
uint8_t lobyte = x & 0xff; // 0x34
3
uint8_t hibyte = x >> 8; // 0x12
Persönliche Seite #616116
Lesenswert?

Punktrichter wrote:
> Doch, seine Art, auf beide Byte zuzugreifen kostet keine Rechenzeit und
> verbraucht minimal Speicherplatz.
> Das kann man bei Deiner (insbesonder die Highbytevariante) nicht
> behaupten.

Nein, weil das Ergebnis seiner Art nirgendwo festgelegt ist und 
Plattform und Compiler abhängig ist.

Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber 
man hat kein Problem mehr mit Compilerabhängigem Gedönsel
Gast #616120
Lesenswert?

1
#include <stdint.h>
2
#include <avr/io.h>
3

4
typedef union
5
{
6
  uint16_t i16;
7
  struct
8
  {
9
    uint8_t l;
10
    uint8_t h;
11
  };
12
} un_i16;
13

14
volatile uint16_t x ;
15
volatile un_i16 y;
16

17
int main(void)
18
{
19
    x = 0x1234;
20
    y.i16 = 0x5678;
21

22
    DDRB = x & 0xff;;
23
    PORTB = x >> 8;;
24
    DDRC = y.l;
25
    PORTC = y.h;
26
}

ergibt:
1
0000005c <main>:
2
volatile uint16_t x ;
3
volatile un_i16 y;
4

5
int main(void)
6
{
7
  5c:   cf e5           ldi     r28, 0x5F       ; 95
8
  5e:   d4 e0           ldi     r29, 0x04       ; 4
9
  60:   de bf           out     0x3e, r29       ; 62
10
  62:   cd bf           out     0x3d, r28       ; 61
11
    x = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  68:   90 93 61 00     sts     0x0061, r25
15
  6c:   80 93 60 00     sts     0x0060, r24
16
    y.i16 = 0x5678;
17
  70:   88 e7           ldi     r24, 0x78       ; 120
18
  72:   96 e5           ldi     r25, 0x56       ; 86
19
  74:   90 93 63 00     sts     0x0063, r25
20
  78:   80 93 62 00     sts     0x0062, r24
21

22
    DDRB = x & 0xff;;
23
  7c:   80 91 60 00     lds     r24, 0x0060
24
  80:   90 91 61 00     lds     r25, 0x0061
25
  84:   87 bb           out     0x17, r24       ; 23
26
    PORTB = x >> 8;;
27
  86:   80 91 60 00     lds     r24, 0x0060
28
  8a:   90 91 61 00     lds     r25, 0x0061
29
  8e:   89 2f           mov     r24, r25
30
  90:   99 27           eor     r25, r25
31
  92:   88 bb           out     0x18, r24       ; 24
32
    DDRC = y.l;
33
  94:   80 91 62 00     lds     r24, 0x0062
34
  98:   84 bb           out     0x14, r24       ; 20
35
    PORTC = y.h;
36
  9a:   80 91 63 00     lds     r24, 0x0063
37
  9e:   85 bb           out     0x15, r24       ; 21
38
}
39
  a0:   80 e0           ldi     r24, 0x00       ; 0
40
  a2:   90 e0           ldi     r25, 0x00       ; 0
41
  a4:   00 c0           rjmp    .+0             ; 0xa6 <_exit>
42

43
000000a6 <_exit>:
44
  a6:   ff cf           rjmp    .-2             ; 0xa6 <_exit>

daran sieht man ganz deutlich, dass die union-variante vorteile hat.
Gast #616129
Lesenswert?

achja, kompiliert mit avr-gcc, optimierung -Os
1
avr-gcc -c -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL  -Os -Wall -Wstrict-prototypes -std=gnu99  main.c -o main.o 
2
avr-gcc -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL  -Os -Wall -Wstrict-prototypes -std=gnu99  main.o   --output main.elf     -lm
3
avr-objcopy -O ihex -R .eeprom main.elf main.hex
Gast #616137
Lesenswert?

> dann kompilier mein beispiel bitte mal mit deinem kompiler und poste das
> asm-listing
ich zeig dir mal'n output vom IAR für ARM:
1
typedef unsigned char uint8_t;
2
typedef unsigned short uint16_t;
3

4
typedef union
5
{
6
  uint16_t i16;
7
  struct
8
  {
9
    uint8_t l;
10
    uint8_t h;
11
  }i8;
12
} un_i16;
13

14
int main()
15
{
16
  un_i16 x;
17
  uint16_t y;
18
  volatile uint8_t a,b,c,d; 
19

20
  x.i16 = 0x1234;
21
  y = 0x1234;
22

23
  a = x.i8.l;
24
  b = x.i8.h;
25

26
  c = y & 0xff;
27
  d = y >> 8;
28
}
ergibt:
1
      1          #include <stdlib.h>
2
      2          #include <string.h>
3
      3          
4
      4          typedef unsigned char uint8_t;
5
      5          typedef unsigned short uint16_t;
6
      6          
7
      7          typedef union
8
      8          {
9
      9            uint16_t i16;
10
     10            struct
11
     11            {
12
     12              uint8_t l;
13
     13              uint8_t h;
14
     14            }i8;
15
     15          } un_i16;
16
     16          
17

18
   \                                 In segment CODE, align 4, keep-with-next
19
     17          int main()
20
     18          {
21
   \                     main:
22
   \   00000000   04D04DE2           SUB      SP,SP,#+4
23
     19            un_i16 x;
24
     20            uint16_t y;
25
     21            volatile uint8_t a,b,c,d; 
26
     22          
27
     23            x.i16 = 0x1234;
28
   \   00000004   3410A0E3           MOV      R1,#+52
29
   \   00000008   481D81E3           ORR      R1,R1,#0x1200
30
   \   0000000C   B210CDE1           STRH     R1,[SP, #+2]
31
     24            y = 0x1234;
32
   \   00000010   3400A0E3           MOV      R0,#+52
33
   \   00000014   480D80E3           ORR      R0,R0,#0x1200
34
     25          
35
     26            a = x.i8.l;
36
   \   00000018   0220DDE5           LDRB     R2,[SP, #+2]
37
   \   0000001C   0020CDE5           STRB     R2,[SP, #+0]
38
     27            b = x.i8.h;
39
   \   00000020   0320DDE5           LDRB     R2,[SP, #+3]
40
   \   00000024   0020CDE5           STRB     R2,[SP, #+0]
41
     28          
42
     29            c = y & 0xff;
43
   \   00000028   0000CDE5           STRB     R0,[SP, #+0]
44
     30            d = y >> 8;
45
   \   0000002C   2004B0E1           LSRS     R0,R0,#+8
46
   \   00000030   0000CDE5           STRB     R0,[SP, #+0]
47
     31          }
48
   \   00000034   0000A0E3           MOV      R0,#+0
49
   \   00000038   04D08DE2           ADD      SP,SP,#+4        ;; stack cleaning
50
   \   0000003C   1EFF2FE1           BX       LR               ;; return
51

52
   Maximum stack usage in bytes:
53

54
     Function CSTACK
55
     -------- ------
56
     main         4
57

58

59
   Segment part sizes:
60

61
     Function/Label Bytes
62
     -------------- -----
63
     main             64
64
      Others           4
65

66
 
67
 68 bytes in segment CODE
68
 
69
 64 bytes of CODE memory (+ 4 bytes shared)
70

71
Errors: none
72
Warnings: none
Gast #616140
Lesenswert?

>ich zeig dir mal'n output vom IAR für ARM:
aendert sich was, wenn x und y auch als volatile deklariert werden?

hier mal dein beispiel mit avr-gcc:
1
int main(void)
2
{
3
  5c:   cb e5           ldi     r28, 0x5B       ; 91
4
  5e:   d4 e0           ldi     r29, 0x04       ; 4
5
  60:   de bf           out     0x3e, r29       ; 62
6
  62:   cd bf           out     0x3d, r28       ; 61
7
  un_i16 x;
8
  uint16_t y;
9
  volatile uint8_t a,b,c,d;
10

11
  x.i16 = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  y = 0x1234;
15

16
  a = x.i8.l;
17
  68:   89 83           std     Y+1, r24        ; 0x01
18
  b = x.i8.h;
19
  6a:   9a 83           std     Y+2, r25        ; 0x02
20

21
  c = y & 0xff;
22
  6c:   8b 83           std     Y+3, r24        ; 0x03
23
  d = y >> 8;
24
  6e:   82 e1           ldi     r24, 0x12       ; 18
25
  70:   90 e0           ldi     r25, 0x00       ; 0
26
  72:   8c 83           std     Y+4, r24        ; 0x04
27
}
Gast #616143
Lesenswert?

vorweg schonmal das ergebnis von avr-gcc mit x und y als volatile:
1
int main(void)
2
{
3
  5c:   c7 e5           ldi     r28, 0x57       ; 87
4
  5e:   d4 e0           ldi     r29, 0x04       ; 4
5
  60:   de bf           out     0x3e, r29       ; 62
6
  62:   cd bf           out     0x3d, r28       ; 61
7
  volatile un_i16 x;
8
  volatile uint16_t y;
9
  volatile uint8_t a,b,c,d;
10

11
  x.i16 = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  68:   9a 83           std     Y+2, r25        ; 0x02
15
  6a:   89 83           std     Y+1, r24        ; 0x01
16
  y = 0x1234;
17
  6c:   9c 83           std     Y+4, r25        ; 0x04
18
  6e:   8b 83           std     Y+3, r24        ; 0x03
19

20
  a = x.i8.l;
21
  70:   89 81           ldd     r24, Y+1        ; 0x01
22
  72:   8d 83           std     Y+5, r24        ; 0x05
23
  b = x.i8.h;
24
  74:   8a 81           ldd     r24, Y+2        ; 0x02
25
  76:   8e 83           std     Y+6, r24        ; 0x06
26

27
  c = y & 0xff;
28
  78:   8b 81           ldd     r24, Y+3        ; 0x03
29
  7a:   9c 81           ldd     r25, Y+4        ; 0x04
30
  7c:   8f 83           std     Y+7, r24        ; 0x07
31
  d = y >> 8;
32
  7e:   8b 81           ldd     r24, Y+3        ; 0x03
33
  80:   9c 81           ldd     r25, Y+4        ; 0x04
34
  82:   89 2f           mov     r24, r25
35
  84:   99 27           eor     r25, r25
36
  86:   88 87           std     Y+8, r24        ; 0x08
37
}
Gast #616145
Lesenswert?

> aendert sich was, wenn x und y auch als volatile deklariert werden?
ja, es kommt jedesmal eine instruction dazu, weil der zugriff auf die 
variablen ja jedesmal neu erfolgen muss.

btw, am besten siehts aus, wenn man die variablen nicht in der funktion 
hat:
1
     26            a = x.i8.l;
2
   \   00000014   0010D0E5           LDRB     R1,[R0, #+0]
3
   \   00000018   0410C0E5           STRB     R1,[R0, #+4]
4
     27            b = x.i8.h;
5
   \   0000001C   0110D0E5           LDRB     R1,[R0, #+1]
6
   \   00000020   0510C0E5           STRB     R1,[R0, #+5]
7
     28          
8
     29            c = y & 0xff;
9
   \   00000024   3410A0E3           MOV      R1,#+52
10
   \   00000028   0610C0E5           STRB     R1,[R0, #+6]
11
     30            d = y >> 8;
12
   \   0000002C   1210A0E3           MOV      R1,#+18
13
   \   00000030   0710C0E5           STRB     R1,[R0, #+7]
kein shift und keine und-verknüpfung.
globale/statische objekte mögen wohl alle compiler lieber ;-)
#616146
Lesenswert?

Mich würde mal interessieren welcher Compiler den in der Praxis Probleme 
mit der union Variante hat.

Ich benutze eigentlich auch immer die union Variante.
Die für mich entscheidenden Vorteile:
- Garantiert eine kurze Laufzeit (unabhängig von Qualität des 
Compilers...)
- Deutlich übersichtlicher als die mask/shift Variante.
- Bisher hatte ich noch keine Probleme ;)

Was ich mir problematisch vorstelle sind big/little endian Systeme.
Aber da habe ich doch das selbe Problem auch beim shiften?
Wenn das Probleme verursacht gewinnt aber auch hier wieder die union 
Variante, dann definiert man halt zwei unions, je nach endian.
Beim shiften müsste man alles direkt im Code ändern
Gast #616149
Lesenswert?

> Was ich mir problematisch vorstelle sind big/little endian Systeme.
das ist der hauptgrund, weshalb man es nicht mit unions machen sollte.

> Aber da habe ich doch das selbe Problem auch beim shiften?
nein, shift und andere operatoren sind unabhängig von der internen 
repräsentation der daten.
Gast #616150
Lesenswert?

nungut, ich geb mich geschlagen. (avr-)gcc braucht den umweg ueber die 
union, um (in diesem fall) effizienten code zu liefern.

das einzige, womit ich nicht einverstanden bin ist die aussage von 
simon:
>Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber
>man hat kein Problem mehr mit Compilerabhängigem Gedönsel
unions sind c-standard und nicht "compilerabhaengiges gedoensel". das 
man sie benutzen muss, um das gleiche ergebnis wie mit teuren 
bezahlkompilern zu erhalten ist aergerlich, aber funktionieren tuts mit 
beiden.

so long, déjà vu.
Persönliche Seite #616153
Lesenswert?

déjà vu wrote:
> unions sind c-standard und nicht "compilerabhaengiges gedoensel".

Ja, unions sind c-standard. Aber nur solange, wie man auf gleichen wegen 
die Daten schreibt/liest. (Sprich: über die gleiche member-variable 
reinschreibt, wie man rausliest)

Wenn man unterschiedliche Union-member zum schreiben und lesen benutzt 
ist das Verhalten nicht mehr im C-Standard definiert.
Gast #616156
Lesenswert?

> unions sind c-standard und nicht "compilerabhaengiges gedoensel".

ja, aber es ist nicht alles genau definiert. der compiler könnte 
padding-bytes einsetzen (um zugriffe zu optimieren) und schon passen 
deine bytes nicht mehr. unions sind dazu da, speicherplatz zu sparen. so 
wie du sie verwendest, ist das verhalten undefiniert (auch wenn's in der 
realität oft gut geht).
Gast #616165
Lesenswert?

bzw, um im kontext zu bleiben:
1
LOBYTE(x) = uart_getc();
2
HIBYTE(x) = uart_getc();

mir ist schon klar, dass das nicht geht; aber gibts dafuer ein 
sinnvolles define?
1
#define LOBYTE(x) ( ((un_i16)(x)).l )

geht naemlich nicht...
Gast #616176
Lesenswert?

ok, mal ein ein konkretes beispiel(vorraussetzung: union-trick 
notwendig, da avr-gcc):
1
ISR(TIMER0_OVF_vect)
2
{
3
    register convert16to8_t counter;
4
    counter.u8h = soft_counter;
5
    counter.u8l = TCNT2;
6
    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
7
        counter.u8h++;
8
    pitch_value = counter.u16 - pitch_counter;
9
    pitch_counter = counter.u16;
10
    status_set(STATUS_PITCH);
11
}

gaebe es da ein #define, mit dem ich das schreiben koennte:
1
HIBYTE(counter)++;

danach suche ich naemlich schon laenger.
1
#define HIBYTE(x) ( ((un_i16)(x)).h )

funktioniert wiegesagt nur als r-value, nicht als l-value.
Gast #616180
Lesenswert?

und unabhaengig davon:
1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
    register convert16to8_t counter;
12
    counter.u8h = soft_counter;
13
 38a:   32 2d           mov     r19, r2
14
    counter.u8l = TCNT2;
15
 38c:   84 b5           in      r24, 0x24       ; 36
16
 38e:   28 2f           mov     r18, r24
17
    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
18
 390:   08 b6           in      r0, 0x38        ; 56
19
 392:   06 fe           sbrs    r0, 6
20
 394:   03 c0           rjmp    .+6             ; 0x39c <__vector_9+0x22>
21
 396:   8f 37           cpi     r24, 0x7F       ; 127
22
 398:   08 f4           brcc    .+2             ; 0x39c <__vector_9+0x22>
23
        counter.u8h++;
24
 39a:   3f 5f           subi    r19, 0xFF       ; 255
25
    pitch_value = counter.u16 - pitch_counter;
26
 39c:   49 01           movw    r8, r18
27
 39e:   8c 18           sub     r8, r12
28
 3a0:   9d 08           sbc     r9, r13
29
    pitch_counter = counter.u16;
30
 3a2:   69 01           movw    r12, r18
31
    status_set(STATUS_PITCH);
32
 3a4:   00 9a           sbi     0x00, 0 ; 0
33
 3a6:   8f 91           pop     r24
34
 3a8:   3f 91           pop     r19
35
 3aa:   2f 91           pop     r18
36
 3ac:   0f 90           pop     r0
37
 3ae:   0f be           out     0x3f, r0        ; 63
38
 3b0:   0f 90           pop     r0
39
 3b2:   1f 90           pop     r1
40
 3b4:   18 95           reti
41
}

das mach mir erstmal einer in c nach... ;)
Gast #616199
Lesenswert?

> ISR(TIMER0_OVF_vect)
> {
>    register convert16to8_t counter;
>    counter.u8h = soft_counter;
>    counter.u8l = TCNT2;
>    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
>        counter.u8h++;
>    pitch_value = counter.u16 - pitch_counter;
>    pitch_counter = counter.u16;
>    status_set(STATUS_PITCH);
>}

probier mal so:
1
ISR(TIMER0_OVF_vect)
2
{
3
    register uint16_t counter;
4
    counter = ((uint16_t)soft_counter << 8) | TCNT2;
5
    if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f) )
6
        counter += 0x100;
7
    pitch_value = counter - pitch_counter;
8
    pitch_counter = counter;
9
    status_set(STATUS_PITCH);
10
}
oder so (mit 8 bit variable)
1
ISR(TIMER0_OVF_vect)
2
{
3
    register uint8_t counter = soft_counter;
4
    if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
5
        counter++;
6
    pitch_value = ((uint16_t)counter << 8) | TCNT2;
7
    pitch_counter = pitch_value;
8
    pitch_value -= pitch_counter;
9
    status_set(STATUS_PITCH);
10
}
ich weiss natürlich nicht ob's noch geht (wegen des TCNT2)...
Gast #616201
Lesenswert?

beide versionen machen die ISR nur laenger, war ja auch nicht anders zu 
erwarten. mir gings eigentlich auch um ein universelles #define fuer r- 
und l-values. das man das auch "konventionell" schreiben kann, war mir 
schon klar. trotzdem danke, dass du dir die muehe gemacht hast, meinen 
code umzuschreiben. aber "lesbarer" wirds dadurch nicht wirklich. das 
mit dem #define waere halt schoen, da man sich die .u16 sparen koennte. 
aber letztlich kommts ja eh nur auf den bytecode an. und den hab ich mir 
schon  mit komischen c-konstrukten zurechtgebogen ;)

der vollstaendigkeit halber:
1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
 38a:   9f 93           push    r25
12
    register uint16_t counter;
13
    counter = ((uint16_t)soft_counter << 8) | TCNT2;
14
 38c:   82 2d           mov     r24, r2
15
 38e:   99 27           eor     r25, r25
16
 390:   38 2f           mov     r19, r24
17
 392:   22 27           eor     r18, r18
18
 394:   84 b5           in      r24, 0x24       ; 36
19
 396:   99 27           eor     r25, r25
20
 398:   28 2b           or      r18, r24
21
 39a:   39 2b           or      r19, r25
22
    if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f)
23
 39c:   08 b6           in      r0, 0x38        ; 56
24
 39e:   06 fe           sbrs    r0, 6
25
 3a0:   04 c0           rjmp    .+8             ; 0x3aa <__vector_9+0x30>
26
 3a2:   2f 37           cpi     r18, 0x7F       ; 127
27
 3a4:   10 f4           brcc    .+4             ; 0x3aa <__vector_9+0x30>
28
        counter += 0x100;
29
 3a6:   20 50           subi    r18, 0x00       ; 0
30
 3a8:   3f 4f           sbci    r19, 0xFF       ; 255
31
    pitch_value = counter - pitch_counter;
32
 3aa:   49 01           movw    r8, r18
33
 3ac:   8c 18           sub     r8, r12
34
 3ae:   9d 08           sbc     r9, r13
35
    pitch_counter = counter;
36
 3b0:   69 01           movw    r12, r18
37
    status_set(STATUS_PITCH);
38
 3b2:   00 9a           sbi     0x00, 0 ; 0
39
 3b4:   9f 91           pop     r25
40
 3b6:   8f 91           pop     r24
41
 3b8:   3f 91           pop     r19
42
 3ba:   2f 91           pop     r18
43
 3bc:   0f 90           pop     r0
44
 3be:   0f be           out     0x3f, r0        ; 63
45
 3c0:   0f 90           pop     r0
46
 3c2:   1f 90           pop     r1
47
 3c4:   18 95           reti
48
}


1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
 38a:   9f 93           push    r25
12
    register uint8_t counter = soft_counter;
13
 38c:   92 2d           mov     r25, r2
14
    if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
15
 38e:   08 b6           in      r0, 0x38        ; 56
16
 390:   06 fe           sbrs    r0, 6
17
 392:   04 c0           rjmp    .+8             ; 0x39c <__vector_9+0x22>
18
 394:   84 b5           in      r24, 0x24       ; 36
19
 396:   8f 37           cpi     r24, 0x7F       ; 127
20
 398:   08 f4           brcc    .+2             ; 0x39c <__vector_9+0x22>
21
        counter++;
22
 39a:   9f 5f           subi    r25, 0xFF       ; 255
23
    pitch_value = ((uint16_t)counter << 8) | TCNT2;
24
 39c:   89 2f           mov     r24, r25
25
 39e:   99 27           eor     r25, r25
26
 3a0:   38 2f           mov     r19, r24
27
 3a2:   22 27           eor     r18, r18
28
 3a4:   84 b5           in      r24, 0x24       ; 36
29
 3a6:   99 27           eor     r25, r25
30
    pitch_counter = pitch_value;
31
 3a8:   69 01           movw    r12, r18
32
 3aa:   c8 2a           or      r12, r24
33
 3ac:   d9 2a           or      r13, r25
34
    pitch_value -= pitch_counter;
35
 3ae:   88 24           eor     r8, r8
36
 3b0:   99 24           eor     r9, r9
37
    status_set(STATUS_PITCH);
38
 3b2:   00 9a           sbi     0x00, 0 ; 0
39
 3b4:   9f 91           pop     r25
40
 3b6:   8f 91           pop     r24
41
 3b8:   3f 91           pop     r19
42
 3ba:   2f 91           pop     r18
43
 3bc:   0f 90           pop     r0
44
 3be:   0f be           out     0x3f, r0        ; 63
45
 3c0:   0f 90           pop     r0
46
 3c2:   1f 90           pop     r1
47
 3c4:   18 95           reti
48
}

so long, déjà vu.

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