C: Addition ohne Übertrag

#1837133
Lesenswert?

Marc schrieb:

> Aber jetzt kommts:  0xFF + 0x01 ist beim anschliesenden Test != 0x00
> wegen dem Carry.

sicher nicht wegen dem Carry.

Eher schon weil du die falschen Datentypen benutzt hast, bzw. dir die 
angewendeten C-Regeln nicht klar sind.

> Gibt es eine Möglichkeit in C ohne Übertrag zu addieren?

Zeig deinen Code.

Schuss ins Blaue: Deine Berechnung wird im Zahlenraum int durchgeführt, 
während du eigentlich unsigned char haben willst. Mit einem Cast sollte 
sich das Problem beheben lassen.
Gast #1837145
Lesenswert?

Code geht leider grad nicht, bin nicht am Entwicklungsrechner.

Der Zahlenraum soll natürlich unsigned char sein. Ich habs mit uint8_t 
gemacht, was ja eigentlich stimmen müsste!?

Und es liegt am Carry, da im erzeugten ASM Code immer erst die normale 
Addition und dann nochmal die Carry-Addition durchgeführt wird. Beim 
anschliessenden Test zeigt der ASM Code, dass zwar das Ergebnis ==0x00 
ist, aber die Carryflags unterschiedlich sind und der Test somit negativ 
ist.
Gast #1837168
Lesenswert?

Hier der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h> 
3
#include <stdint.h>
4
#include <util/delay.h>
5

6
#include "USI_TWI_Slave.h"
7

8
#define SLAVE_ADDRESS 0x10
9

10
uint8_t command, value, checksum;
11

12

13

14
void Process_Data(void)
15
{
16
  if((SLAVE_ADDRESS + command + value) == checksum)
17
  {
18
.
19
.
20
.

Wo funktionierts??
Gast #1837172
Lesenswert?

Und hier gleich mal noch der Assemblercode:
1
@00000030: Process_Data
2
45:       {
3
+00000030:   91400086    LDS       R20,0x0086     Load direct from data space
4
+00000032:   91800089    LDS       R24,0x0089     Load direct from data space
5
+00000034:   E090        LDI       R25,0x00       Load immediate
6
+00000035:   0F84        ADD       R24,R20        Add without carry
7
+00000036:   1D91        ADC       R25,R1         Add with carry
8
+00000037:   9640        ADIW      R24,0x10       Add immediate to word
9
+00000038:   91200088    LDS       R18,0x0088     Load direct from data space
10
+0000003A:   E030        LDI       R19,0x00       Load immediate
11
+0000003B:   1782        CP        R24,R18        Compare
12
+0000003C:   0793        CPC       R25,R19        Compare with carry
13
+0000003D:   F4F9        BRNE      PC+0x20        Branch if not equal
Gast #1837196
Lesenswert?

Detlev T. schrieb:
> Ich vermute, du speicherst die Prüfsumme nich in einer uint8_t Variable
> vor dem Vergleich, sondern machst den direkt. Berechnungen werden in C
> im Gültigkeitsbereich von int durchgeführt. Du könntest aber die unteren
> 8 Bit mit einem binären UND maskieren.

Dem würde ich mich anschließen. Das nennt sich übrigens "integral 
promotion".
IAR hat einen schönen Beitrag über das Problem gemacht:

http://supp.iar.com/Support/?note=12582&from=search+result
#1837212
Lesenswert?

Marc schrieb:

>   if((SLAVE_ADDRESS + command + value) == checksum)

dir ist hoffentlich klar, dass der linke Teil (die Berechnung) als int 
Berechnung gemacht wird, laut C-Spezifikation

Damit wird auch der rechte Teil auf int hochgehoben und der Vergleich 
auch als int Vergleich gemacht.

> Und es liegt am Carry

Es liegt eben nicht am Carry. In C gibt es gar keinen Carry.
Es liegt daran, dass du fälschlicherweise annimmst, dass 2 unsigned char 
zusammenaddiert wieder einen unsigned char ergeben. Dem ist aber nicht 
so!

Berechnungen werden in C niemals in einem kleineren Datentyp als dem 
Datentyp int gemacht (*). In diesem Sinne sind
1
  if((SLAVE_ADDRESS + command + value) == checksum)

und
1
  uint8_t summ = SLAVE_ADDRESS + command + value;
2
  if(summ  == checksum)
3
    ...

2 völlig verschiedene Paar Schuhe!


(*) Es sei denn, der Optimizer kann beweisen, dass sich das Ergebnis 
nicht verändert, wenn er (bei einem 16 Bit int) das High-Byte ignoriert 
und nicht berechnet. Bei dir unterscheiden sich aber die Ergebnisse, 
daher muss die Berechnung als int-Berechnung gemacht werden.

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