Forum: Mikrocontroller und Digitale Elektronik Routine, die Arrays von Structs kopiert funktioniert unerklärlicherweise nicht.


von Raphael F. (erdbewohner)


Angehängte Dateien:

Lesenswert?

Hallo!
Die untersten 3 Zeilen meines c-Codes sollten den von *startPointer bis 
*endPointer definierten Array in localArray kopieren. Ich habe mich 
schon langsam daran gewöhnt, dass der Gelbe Pfeil im Simulator teilweise 
recht herumhüpft und das macht er auch hier. Nach dem er definitiv nicht 
mehr ins for zurückhüpft, ist der *number-Pointer aber nicht der gleiche 
wie der des gleichen Eintrages in startPointer. Ich verstehe das nicht!
Ich arbeite mit AVR-Studio 5, einem AT-MEGA32 und optimierungsstufe -Os.
Ich habe noch zwei vorher- nachher-screenshots des Simulators gepostet.
Ich hoffe ihr könnt mir helfen!
Gruss
Erdbewohner
1
struct SignAndNumber
2
{
3
  enum MathSign sign;
4
  double *number;
5
};
6
7
...
8
int main(void)
9
{
10
  struct SignAndNumber san1;
11
    san1.sign = keines;
12
    san1.number = &numberArray[0];
13
    
14
  problemArray[0] = san1;
15
  
16
  double result;
17
  result = solve(&problemArray[0], &problemArray[0]);
18
}
19
double solve(struct SignAndNumber *startPointer, struct SignAndNumber *endPointer)
20
{
21
  uint8_t localLength = (startPointer-endPointer+3)/3;
22
  struct SignAndNumber localArray[localLength];
23
  for(uint8_t i = 0; i < localLength; i++)
24
  {
25
    localArray[i] = *(startPointer+i);
26
  }

von Oktavian G. (Firma: Hochschule Karlsruhe) (tavin)


Lesenswert?

ich wurde Sagen da fehlt ein "volatile" bei der definition der Variablen 
der Struktur

struct SignAndNumber
{
 volatile  enum MathSign sign;
  volatile  double *number;
};

von Raphael F. (erdbewohner)


Angehängte Dateien:

Lesenswert?

So, und hier noch der erste Screenshot.

von Raphael F. (erdbewohner)


Lesenswert?

Danke für die schnelle Antwort, aber es hilft leider nichts. Genau das 
gleiche.

von Oktavian G. (Firma: Hochschule Karlsruhe) (tavin)


Lesenswert?

mal mit "-O0" versuchen, dan springt der Pfeil nicht so wild herum ;) 
wenn es dann geht, ist es ein Optimierungsproblemm.

von Raphael F. (erdbewohner)


Lesenswert?

Danke. Mit -O0 funktioniert es. Aber mit -O1 schon nicht mehr. Ich kann 
aber nicht meinen ganzen Code mit O0 kompilieren, da wird er ja ewig 
langsam und riesig.
Gibt es noch andere Ratschläge?

von Karl H. (kbuchegg)


Lesenswert?

> uint8_t localLength = (startPointer-endPointer+3)/3;

Wieso   +3) / 3


So wie du das aufrufst
  solve(&problemArray[0], &problemArray[0]);

ist der Ausdruck
   startPointer-endPointer
gleich 0. Noch 3 dazu, macht 3, durch 3 macht 1

Die Schleife wird also 1 mal durchlaufen.

von Raphael F. (erdbewohner)


Lesenswert?

das +3 weil die länge eines mehr als der Start-pointer minus der 
endpointer ist. (siehe mein Test-beispiel mit einem 1-elemente-array: 
sonst wäre die länge 0).
das /3, weil ein SignAndNumber-struct 3 Bytes gross ist und ich in 
localLength die Anzahl Elemente in localArray haben möchte.

von Karl H. (kbuchegg)


Lesenswert?

Raphael F. schrieb:

> Gibt es noch andere Ratschläge?

Zeig mal alles.

Im Zweifelsfall trau ich dem Compiler eher über den Weg.

von Karl H. (kbuchegg)


Lesenswert?

Raphael F. schrieb:
> das +3 weil die länge eines mehr als der Start-pointer minus der
> endpointer ist. (siehe mein Test-beispiel mit einem 1-elemente-array:
> sonst wäre die länge 0).
> das /3, weil ein SignAndNumber-struct 3 Bytes gross ist

No.
Das rechnet der COmpiler bei Pointerarithmetik von alleine ein.
Ausserdem ist die Anzahl immer noch Ende - Start.

Bei
  *(startPointer+i)
hast du ja die Strukturgröße auch nicht berücksichtigen müssen.

> und ich in
> localLength die Anzahl Elemente in localArray haben möchte.

Die vernünftigste Methode ist es nicht, da einen Endpointer mitzugeben. 
Vernünftig wäre es, wenn der Aufrufer gleich mitteilt was Sache ist und 
die Anzahl mit übergibt.

von Karl H. (kbuchegg)


Lesenswert?

> Aber mit -O1 schon nicht mehr.

Je nachdem wies weitergeht, könnte der Compiler das komplette Array 
komplett wegoptimiert haben.

von Raphael F. (erdbewohner)


Angehängte Dateien:

Lesenswert?

Also: Das, was kbuchegg vorgeschlagen hat habe ich geändert. Es ändert 
aber nichts. Das mit der länge anstatt endPointer ist auch eine gute 
Idee. Es sollte aber nichts mit unserem Problem zu tun haben. Ich werde 
das später mal ändern.
der komplette Code (es soll mal ein "Taschenrechner" werden, bei dem man 
die Rechnung so eingeben kann, wie sie auf dem Papier steht) ist 
angehängt.

von Raphael F. (erdbewohner)


Lesenswert?

>Je nachdem wies weitergeht, könnte der Compiler das komplette Array
>komplett wegoptimiert haben.

Ja, das war auch so, als ich den restlichen Code auskommentiert habe. 
Ich habe aber noch einige Versuche gemacht, wo er den Inhalt von 
localArray irgendwie verrechnet und dann an ein Port ausgibt. Dann kann 
der Compiler ihn ja nicht mehr wegoptimieren. Es hat trotzdem nicht 
funktioniert. :-(

von Karl H. (kbuchegg)


Lesenswert?

UI. Das habt ihr aber kompliziert aufgebaut. (Und vor allem viel zu viel 
Code geschrieben ohne zwischendruch wieder mal ausreichend zu testen)
WIrd ne weile dauern bis ich das aufgedröselt habe.

Auf jeden Fall habt ihr den 3-er Fehler noch ein paar mal gemacht.
Und eine Arraylänge errechnet sich mittels Ende - Anfang. Nicht anders 
rum.

uint8_t localLength = ( endPointer - startPointer ) + 1;

von Raphael F. (erdbewohner)


Lesenswert?

Ich weiss, es gibt sicher noch viele Fehler zu beheben. Aber leider ist 
alles das nicht die Lösung für das Problem.
Ein uneleganter, aber simpler Ausweg wäre, eine kleine 
inline-Assembler-Routine zu schreiben. :-/
Ich gehe jetzt aber ins Bett.
Und danke für die Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

Ja da sind ein paar Fehler drinnen. Die Klammernauswertung wird zu 
Fehlern führen und SetBack geht so gar nicht. Aber das findet ihr 
selber.

Mit Pointers stehst du noch ein wenig auf Kriegsfuss. Solange du da 
nicht sicherer bist, solltest eventuell die Arrayschreibweise benutzen.
1
  for(uint8_t i = 0; i < localLength; i++)
2
  {
3
    localArray[i] = startPointer[i];
4
  }

und den Dualismus zwischen

   (*a).n   <==>   a->n

hast du auch noch nicht durchschaut, aber das ist jetzt erst mal nicht 
so wichtig.

OK. Was passiert, wenn du im Debugger weiterstepst? Kriegt localArray[0] 
irgendwann mal seine Werte?

von Karl H. (kbuchegg)


Lesenswert?

Das ist zuviel Code auf einmal geschrieben. Das kriegst du so nicht zum 
laufen.

Code schrittweise aufbauen!

erst mal mit
1
double solve(struct SignAndNumber *startPointer, struct SignAndNumber *endPointer)
2
{
3
  uint8_t localLength = ( endPointer - startPointer ) + 1;
4
  struct SignAndNumber localArray[localLength];
5
6
  for(uint8_t i = 0; i < localLength; i++)
7
  {
8
    localArray[i] = startPointer[i];
9
  }
10
  
11
  return *(localArray[0].number);
12
}
anfangen.


Das dann erweitern, dass der Auswerter mit einem '+' zurechtkommt. Nicht 
mehr!
1
double solve(struct SignAndNumber *startPointer, struct SignAndNumber *endPointer)
2
{
3
  uint8_t localLength = ( endPointer - startPointer ) + 1;
4
  struct SignAndNumber localArray[localLength];
5
6
  for(uint8_t i = 0; i < localLength; i++)
7
  {
8
    localArray[i] = startPointer[i];
9
  }
10
  
11
12
  for(uint8_t i = 1; i < localLength; i++)
13
  {
14
    switch( localArray[i].sign )
15
    {
16
      case plus:
17
        //
18
        //          i
19
        //           |
20
        //           v
21
        //   +----+-----+----+----+----+----+
22
        //   | z1 |  +  | z2 | a  | b  | c  |
23
        //   +----+-----+----+----+----+----+
24
        //           |
25
        //           |  r <- z1 + z2
26
        //           v
27
        //   +----+-----+----+----+
28
        //   | r  | a   | b  | c  |
29
        //   +----+-----+----+----+
30
        //
31
        //  z1 wird durch  z1 + z2 ersetzt
32
        //  der Rest vom Array um 2 Stellen nach vorne geschoben
33
        //  i muss korrigiert werden, damit es im naechsten Schleifendurchlauf
34
        //  wieder an der Stelle mit dem a weitergeht
35
        // 
36
37
        // ALso: Additionsergebnis berechnen
38
        *(localArray[i-1].number) = *(localArray[i-1].number) + *(localArray[i+1].number);
39
40
        // Array um 2 Elemente zusammenschieben
41
        // laut Zeichnung muss das 'a' Element auf dem '+' zu liegen
42
        // kommen.
43
        // Ziel ist also   localArray[i]
44
        // Quelle ist      localArray[i+2]
45
        // und kopiert werden müssen locallength - i - 2 Elemente (in der Zeichnung kontrollieren
46
        //        ( im Beispiel:   6 - 1 - 2 = 3
47
        //                 also 3 Elemente. Stimmt genau. Das sind a b und c )
48
        setArrayBack(&localArray[i], &localArray[i+2], localLength - i - 2);
49
50
        // das Array ist jetzt um 2 Einträge kürzer
51
        localLength -= 2;
52
53
        // und i korrigieren für den nächsten Schleifendurchlauf
54
        i--;
55
        break;
56
    }
57
  }
58
59
  return *(localArray[0].number);
60
}
61
62
//
63
// Kopiert Array Elemente um (schiebt das Array zusammen)
64
//
65
// Kopiert size Elemente beginnend bei source nach destination um
66
void setArrayBack( struct SignAndNumber *destination,
67
                   struct SignAndNumber *source,
68
                   uint8_t size )
69
{
70
  for( uint8_t i = 0; i < size; ++i )
71
  {
72
    destination[i] = source[i];
73
  }
74
}

Mach dir klar, warum dieser Code genau so und nicht anders ist. Mach dir 
Zeichnungen wleche Werte miteinander verrechnet werden müssen, welche 
Werte wohin kopiert werden müssen.

Wenn das dann mit 1 '+' funktioniert, dann probier Ausdrücke mit 
mehreren Additionen ( 2.0 + 5.0 + 8.0 )

Das muss funktionieren! Vorher ist es sinnlos wenn ihr den Code 
erweitert. Ihr verliert euch sonst in der Komplexität!

Wenn Additionen klappen dann kümmert euch um Subtraktionen. Das wird 
ganz ähnlich aussehen wie Additionen.

Klappen dann Subtraktionen, dann macht ihr Multiplikationen.

Wieder: testen, testen, testen.

Danach würde ich mal die Klammern in Angriff nehmen. Die Idee die ihr da 
habt, kann man so machen. Dass man im Vorfeld erst mal Klammern 
auswerten und den Klammerausdruck durch den Wert ersetzen lässt. Das 
wird euch eine Weile beschäftigen.

Und erst dann kommen die Gimmicks wie Wurzel oder Sinus.


Das was ihr da aufbaut ist ziemlich komplex aufgebaut. Wenn ihr euch 
einen zu großen Brocken auf einmal abbeisst, werdet ihr daran ersticken. 
Daher: Kleine Bissen und den dann gut kauen (== testen)!

Macht euch in den Code Notizen in Form von Kommentaren rein, aus denen 
ersichtlich ist, wie die Arrays manipuliert werden müssen! Speziell wenn 
ihr dann bei der Klammerauswertung seid, wird das essentiell. So wie ich 
das sehe solltet ihr Pointer noch vermeiden. Arbeitet lieber mit 
Indizes, das könnt ihr noch besser durchschauen. In einer Zeichnung kann 
man dann leicht abzählen, welcher Index sich wie ergibt.

von Karl H. (kbuchegg)


Lesenswert?

Noch ein Hinweis.

Deine main kannst du dir einfacher machen.

Du kannst den auszuwertenden Ausdruck so zusammensetzen.
1
//
2
//  2.0 + 3.0 + 5.0
3
//
4
double numbers[] = {2.0, 3.0, 5.0};
5
struct SignAndNumber Expression[] =
6
{
7
  { keines, &numbers[0] },
8
  { plus,   NULL },
9
  { keines, &numbers[1] },
10
  { plus,   NULL },
11
  { keines, &numbers[2] },
12
};
13
14
#define ARRAY_SIZE(x)  (sizeof(x) / sizeof(*x))
15
16
int main()
17
{
18
  double result;
19
  result = solve(&Expression[0], &Expression[ARRAY_SIZE(Expression)]);
20
}

Das wird dann bei komplexeren Ausdrücken übersichtlicher und einfacher 
in der Verwendung als wie wenn du da erst Einzelstrukturobjekte 
zusammenpfriemelst.

von Karl H. (kbuchegg)


Lesenswert?

Aber je mehr ich mir das überlege, desto weniger bin ich von dem Konzept 
überzeugt. Die Idee mit dem Ersetzen ist gar nicht so gut. Ihr zrstört 
euch die Zahlen im number Array. Bei Zahlen ist das noch wurscht aber 
spätestens wenn dann Variablen ins Spiel kommen wird das haarig.

Die klassische Stackmaschine wäre besser gewesen. Ist auch einfacher zu 
implementieren.

von Martin (Gast)


Lesenswert?

Oktavian Gniot schrieb:
> ich wurde Sagen da fehlt ein "volatile" bei der definition der Variablen
> der Struktur

Und warum würdest du das sagen?

Weißt du überhaupt, was volatile bedeutet? Oder wolltest du nur auch mal 
was sagen?

von Raphael F. (erdbewohner)


Lesenswert?

Ok......
Vielen Dank für all die Tipps und Ratschläge! Ich werde sie nun 
versuchen umzusetzen und werde den Code dann nochmals hier posten.

>Aber je mehr ich mir das überlege, desto weniger bin ich von dem Konzept
>überzeugt. Die Idee mit dem Ersetzen ist gar nicht so gut. Ihr zrstört
>euch die Zahlen im number Array. Bei Zahlen ist das noch wurscht aber
>spätestens wenn dann Variablen ins Spiel kommen wird das haarig.
Meinst du mit Variablen ein CAS-System? Falls ja: Das habe ich erstmal 
nicht vor zu implementieren. Ich bin schon sehr froh, wenn das jetzige 
läuft.

>Die klassische Stackmaschine wäre besser gewesen. Ist auch einfacher zu
>implementieren.
Kannst du das etwas genauer beschreiben?

von Karl H. (kbuchegg)


Lesenswert?

Raphael F. schrieb:

>>euch die Zahlen im number Array. Bei Zahlen ist das noch wurscht aber
>>spätestens wenn dann Variablen ins Spiel kommen wird das haarig.
> Meinst du mit Variablen ein CAS-System? Falls ja: Das habe ich erstmal
> nicht vor zu implementieren.

Dann frag ich mich, wozu du den double Pointer in die Struktur mit 
aufgenommen hast. Nimm doch den double direkt mit in die Struktur, das 
vereinfacht das alles wieder ein bischen. Wenn es nicht sein muss, 
benutzt man keine Pointer, nur weil es so lustig ist.
1
struct SignAndNumber
2
{
3
  volatile enum MathSign sign;
4
  volatile double        number;
5
};
6
7
....
8
9
//
10
//  2.0 + 3.0 + 5.0
11
//
12
struct SignAndNumber Expression[] =
13
{
14
  { keines, 2.0 },
15
  { plus,   0.0 },
16
  { keines, 3.0 },
17
  { plus,   0.0 },
18
  { keines, 5.0 },
19
};
20
21
#define ARRAY_SIZE(x)  (sizeof(x) / sizeof(*x))
22
23
int main()
24
{
25
  double result;
26
  result = solve(&Expression[0], &Expression[ARRAY_SIZE(Expression)]);
27
}

und die solve Funktion natürlich entsprechend anpassen. Da werden dann 
einige 'Sonderzeichen' wegfallen :-)

>>Die klassische Stackmaschine wäre besser gewesen. Ist auch einfacher zu
>>implementieren.
> Kannst du das etwas genauer beschreiben?

http://www.arstdesign.com/articles/expression_evaluation.html

von Raphael F. (erdbewohner)


Lesenswert?

>Dann frag ich mich, wozu du den double Pointer in die Struktur mit
>aufgenommen hast. Nimm doch den double direkt mit in die Struktur, das
>vereinfacht das alles wieder ein bischen. Wenn es nicht sein muss,
>benutzt man keine Pointer, nur weil es so lustig ist.

Weil bei allen Zeichen der Wert garnicht relevant ist. Dort ist der 
Pointer dann einfach 0x0000 oder sowas und wird auch nie beachtet. Das 
verbraucht weniger Speicher als wenn ich jedesmal ein 0x0000000000000000 
(8 Byte für ein Double) habe.

von tavin (Gast)


Lesenswert?

Ich hab

Martin schrieb:
> Oktavian Gniot schrieb:
>> ich wurde Sagen da fehlt ein "volatile" bei der definition der Variablen
>> der Struktur
>
> Und warum würdest du das sagen?
>
> Weißt du überhaupt, was volatile bedeutet? Oder wolltest du nur auch mal
> was sagen?

nein, Ich habe nur mal so eben irgendwo gehört das sei das Zauberwort 
das alle Programieierungsproblemme automatisch löst.

von Karl H. (kbuchegg)


Lesenswert?

tavin schrieb:
> Ich hab
>
> Martin schrieb:
>> Oktavian Gniot schrieb:
>>> ich wurde Sagen da fehlt ein "volatile" bei der definition der Variablen
>>> der Struktur
>>
>> Und warum würdest du das sagen?
>>
>> Weißt du überhaupt, was volatile bedeutet? Oder wolltest du nur auch mal
>> was sagen?
>
> nein, Ich habe nur mal so eben irgendwo gehört das sei das Zauberwort
> das alle Programieierungsproblemme automatisch löst.

Leider falsch.

von tavin (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

>> nein, Ich habe nur mal so eben irgendwo gehört das sei das Zauberwort
>> das alle Programieierungsproblemme automatisch löst.
>
> Leider falsch.

Mein Weltbild Bricht zusammen...... :(

von Karl H. (kbuchegg)


Lesenswert?

Raphael F. schrieb:
>>Dann frag ich mich, wozu du den double Pointer in die Struktur mit
>>aufgenommen hast. Nimm doch den double direkt mit in die Struktur, das
>>vereinfacht das alles wieder ein bischen. Wenn es nicht sein muss,
>>benutzt man keine Pointer, nur weil es so lustig ist.
>
> Weil bei allen Zeichen der Wert garnicht relevant ist. Dort ist der
> Pointer dann einfach 0x0000 oder sowas und wird auch nie beachtet. Das
> verbraucht weniger Speicher als wenn ich jedesmal ein 0x0000000000000000
> (8 Byte für ein Double) habe.


Was sagt dir

'Premature optimization is the root of all evil'

Schaun wir mal, wie gross die Einsparung wirklich ist.

Ausdruck   2 + 3

alte Struktur

  2 Zahlenknoten, macht       2 * 3 Bytes       6
  1 Operatorknoten            3 Bytes           3
  2 Einträge im double Array  2 * 8            16
                                            ------
                                               25

neue Struktur

  3 Knoten a 9 Bytes                           27 Bytes


OK. du brauchst 2 Bytes weniger. Dafür hast du eine zusätzliche 
Fehlerquelle (das Zahlenarray kann zu klein dimensioniert sein) und der 
Code wird komplizierter.


(PS: so wie es aussieht, benutzt du den gcc. Bei dem sind auf dem AVR 
double nur 4 Bytes gross. Die Rechnung steht dann  6 + 3 + 8 = 17  gegen 
3 * 5 = 15, und die neue Struktur gewinnt.

von Raphael F. (erdbewohner)


Lesenswert?

>Weil bei allen Zeichen der Wert garnicht relevant ist. Dort ist der
>Pointer dann einfach 0x0000 oder sowas und wird auch nie beachtet. Das
>verbraucht weniger Speicher als wenn ich jedesmal ein 0x0000000000000000
>(8 Byte für ein Double) habe.

Aber ich habe gerade bemerkt, dass mir das einige Probleme bereitet 
(z.B. wenn ich bei der Auflösung von Klammern die letzte Klammer in eine 
Zahl "verwandle"). Ich werde die doubles doch direkt in den Struct 
nehmen. Wenn ich speicherprobleme kriege, muss ich das halt noch 
irgendwie verbessern...

von Karl H. (kbuchegg)


Lesenswert?

Darf ich fragen, was du machst.

Bist du Schüler, Student? Auf welchem Level arbeitest du?


Der Grund: So wie du das angehst, ist das sehr aufwändig. Du musst 
nämlich zuerst einmal aus der textuellen Eingabe dein Array aufbauen, 
wobei sich natürlich das Problem ergibt, wie du das dimensionierst. Die 
Sache mit der Ersetzung sieht zwar auf den ersten Blick logisch aus, ist 
aber in der Praxis ziemlich aufwändig, wie du schon gemerkt hast. Durch 
das ständige Array hin und her schaufeln wird es dann auch noch ziemlich 
langsam. Kurz und gut: eigentlich hat das überhaupt keinen Vorteil, 
ausser das es mehr oder weniger 1:1 der Vorgehensweise in der 
Satzableitung entspricht, wie man sie in der Theorie der formalen 
Sprachen lernt, wenn man versucht einen Eingabetext anhand der Grammatik 
als Satz dieser Grammatik durch bottom up Ersetzungen zu beweisen.

Du könntest
* einen Parser bauen, der direkt auf dem Eingabetext aufsetzt.
* der eine Stackmaschine wie im besagten Link benutzt

* oder aber zb einen Recursive Descent Parser bzw. Evaluator 
implementiert.

Solange du einen arithmetischen Ausdruck nicht umformen musst (zb um ihn 
zu vereinfachen oder zb ihn zu differenzieren), sondern ihn nur 
Evaluieren musst, bringt das Überführen in eine spezielle Struktur mit 
Knoten nichts. Das eigentliche Problem wird dadurch nicht einfacher, du 
hast nur die Daten in eine etwas strengere Form gebracht.

Ich weiss aber nicht, ob ich dir insbesondere letzteres empfehlen soll, 
das geht schon ein bischen in Compilerbau hinein (dieselben Techniken) 
und ist in der Theorie schon ein wenig anspruchsvoll auch wenn die 
Implementierung danach relativ einfach ist (wenn man die Theorie intus 
hat)

von Raphael F. (erdbewohner)


Lesenswert?

Wow!
Das mit der Stackmaschine ist (klingt auf jeden fall) ja voll Simpel! Es 
wäre auf jeden Fall fiel schneller! Dass ich bei meiner jetzigen 
Variante noch einen zweiten text-parser brauche weiss ich.
Ich bin übrigens in der 11. Klasse (und gehe in der Schweiz zur Schule, 
dort haben wir noch 13 Jahre).

von Raphael F. (erdbewohner)


Angehängte Dateien:

Lesenswert?

Also, ich habe jetzt meinen Code umgeschrieben: So weit wie möglich auf 
Pointer verzichtet usw...
Das Problem mit dem Kopieren der struct-Arrays bleibt aber. Ich habe 
einen Screenshot des Disassembly gemacht. Die Stelle
1
000001B6  LD R0,Z+    Load indirect and postincrement 
2
000001B7  ST X+,R0    Store indirect and postincrement

geht er 5 mal durch (so gross ist das zu kopierende struct). Am Anfang 
ist der Z-pointer auch auf der richtigen stelle, aber der X-pointer ist 
auf 0x0839 anstatt 0x083D (die Adresse von localArray)

Die Zeilen
1
for(double i = 0; i < result; i = i+0.12345)
2
{
3
  PORTB = (uint8_t)i*12345;
4
}
sind nur dazu da, dass der compiler result nicht ignorieren kann (sonst 
würde er es vllt. wegoptimieren)

von Raphael F. (erdbewohner)


Lesenswert?

Ich habe den Compiler (wenn auch nur eher provisorisch) überlistet:
1
struct SignAndNumber localArray[length];
2
uint8_t localLength = length;
3
asm volatile("push r18"::);
4
asm volatile("ldi r18, 4"::);
5
asm volatile("add r16, r18");
6
asm volatile("adc r17, __zero_reg__"::);
7
asm volatile("pop r18");
8
for(uint8_t i = 0; i < localLength; i++)
9
{
10
   localArray[i] = expression[i];
11
}
Da die Adresse von localArray vorher in r16/r17 ist, habe ich einfach 
per inline-Assembler r16 und r17 um 4 erhöht, sodass sie jetzt auf 
0x083D zeigen. Sobald der Compiler ein anderes Register nimmt muss ich 
es halt anpassen... (eben: nur provisorisch)

von Raphael F. (erdbewohner)


Lesenswert?

Ich habe noch eine andere Theorie: Die Watch ist falsch.
Denn wenn ich es mit "Korrektur" (siehe letztem Post) laufen lasse, 
springt er innerhalb von solve(), nicht so, wie er sollte. Jedoch ohne 
Korrektur springt er genau so, wie er sollte (was heisst, dass die werte 
in localArray eigentlich stimmen sollten). Ich werde es nun einfach mal 
ohne Korrektur weitertesten und schauen, ob es stimmt...

von Raphael F. (erdbewohner)


Angehängte Dateien:

Lesenswert?

Ja: die watch ist falsch (wird hoffentlich irgendwann mit einem update 
beseitigt). Ich lasse den Code nun ohne irgendeine Änderung bezüglich 
der Array-Kopier-Funktion laufen, und er funktioniert schon sehr gut 
(Klammern kombiniert mit +-*/ läuft perfekt :-))) )!
Ich glaube, ich werde ihn vorerst nicht auf die Stackmaschine 
umschreiben, da er auch so (mit 16MHz) genügend schnell sein sollte.
Vielen Dank für die ganze Hilfe, die Tipps und Ratschläge, kbuchegg!!
Ich habe nocheinmal den Code in der aktuellen Version gepostet.

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.