Hier aber passt es nicht mehr, jetzt müsste die Variable 'volatile
uint16_t Zeit' ja an Adresse 0x0000 & 0x0064 liegen. Das kann aber aus
zwei Gründen nicht sein. Die Adresse 0x0000 sollte das Register R0 sein,
ist also nicht im Ram. Und folgender Code wiederspricht dem:
Wenn die Optimierung eingeschaltet ist, kann der Compiler eine ganze
Menge machen, was für den Menschen nicht auf den ersten Blick
verständlich ist. Möglicherweise steht in R0 ja genau der Wert der an
der Stelle benötigt wird. Ist aus den Codeschnipseln nicht zu erkennen.
Die einzig wichtige Frage hier lautet: _Tut der Code das was er soll?_
"Die einzig wichtige Frage hier lautet: _Tut der Code das was er soll?_"
Nein tut er nicht.
"Möglicherweise steht in R0 ja genau der Wert der an
der Stelle benötigt wird."
kann eigentlich nicht sein Variable ist ja volatile.
Gruß Rene
Der Output sieht nach dem Disassembler-Fenster vom AVR-Studio aus. Ich
meine, ich hätte ähnliches auch schon gehabt, was aber ein Fehler vom
AVR-Studio war. Schau also besser erstmal im HEX-File nach, was
tatsächlich dort steht.
Oder schau in das LSS-File, auch dem würde ich eher trauen, als dem
AVR-Studio.
Top Soft wrote:
> kann eigentlich nicht sein Variable ist ja volatile.
Das heißt aber nicht, dass der Compiler in jeder Mikrosekunde damit
rechnet, dass dieser Wert geändert wird. Das ginge schon deshalb nicht,
weil zum Beispiel 16-Bit-Variablen in einem 8-Bit-AVR nicht atomar
gelesen oder geschrieben werden können.
Es geht, so wie ich das verstanden habe, eher darum, dem Compiler
mitzuteilen, dass eine Variable außerhalb des aktuellen Blocks (oder
Funktion?) geändert werden kann, um bestimmte Optimierungen zu
verhindern. Wie zum Beispiel so etwas:
1
volatileuint8_ttimer_count=0;
2
3
while(1)
4
{
5
/* Tue irgendwas ohne timer_count zu ändern */
6
if(timer_count>50)/*Tuewasanderes*/;
7
}
Ohne volatile könnte er hier die if-Abfrage wegoptimieren.
Um auf dein Beispiel zurück zu kommen. Ich vermute, dass zu diesem
Zeitpunkt der Wert aus Adresse 0x0063 aus einer vorherigen Berechnung
noch in dem temporären Register R0 ist. Das läßt sich aus den
Schnipseln, die du präsentiert hast, natürlich nicht ablesen. Dann wäre
der Code weder falsch noch langsamer als wenn man aus Adresse 0x0063
lesen würde.
schon alleine wenn ich das hier sehr wird mir schlecht
else{ // wenn das Relais an ist
if( get_key_press( 1<<KEY0 )){ // ist Taste gedrückt?
PORTB &= ~(1<<PB0); // Relais an PB0 aus
Status.Relais = 0;
du springst in die else und frägst dann was mit if ab
und was machste wenn die if nicht war ist
"Ich vermute, dass zu diesem Zeitpunkt der Wert aus Adresse 0x0063 aus
einer vorherigen Berechnung noch in dem temporären Register R0 ist. Das
läßt sich aus den Schnipseln, die du präsentiert hast, natürlich nicht
ablesen. Dann wäre der Code weder falsch noch langsamer als wenn man aus
Adresse 0x0063 lesen würde."
Nicht langsamer? LDI braucht 3 Takte, wenns schon im Register ist braut
es keinen!
Gruß Rene
> Hier der Ausschnitt aus der main.sym .
Das war jetzt aber die falsche Stelle zum nachschauen, denn was sagt das
aus über den erzeugen Assembler-Code?
"Das war jetzt aber die falsche Stelle zum nachschauen, denn was sagt
das
aus über den erzeugen Assembler-Code?"
nichts, aber über die Lage der Variablen im Ram.
Gruß Rene
bingo wrote:
> du springst in die else und frägst dann was mit if ab> und was machste wenn die if nicht war ist
Na nichts. Was soll daran problematisch sein?
Top Soft wrote:
> nichts, aber über die Lage der Variablen im Ram.
Die stand doch schon im ersten Post fest.
Du weißt aber immer noch nicht, ob da nun tatsächlich "LDS R24,0x0000"
im Code steht, oder nicht.
Top Soft wrote:
> Nicht langsamer? LDI braucht 3 Takte, wenns schon im Register ist braut> es keinen!
Sehr witzig! Ich meinte selbstverständlich "LDI R24,0x0063" im Vergleich
zu "LDI R24,0x0000". Natürlich könnte man hier die Subtraktion gleich
auf R0 ausführen und noch ein paar Byte und Taktzyklen sparen. Es wird
immer wieder Fälle geben, wo der vom Compiler erzeugte Code etwas
schlechter ist als ein von Hand optimierter.
Nachtrag: Welche Optimierungs"stufe" hast du überhaupt aktiviert.
Vielleicht kann das der Compiler sogar noch verbessern.
@ Detlev T.:
Wenn der Compiler hier tatsächlich vor hätte r0 zu verwenden (und ich
bin nicht deiner Meinung, dass er es hier dürfte), dann würde er das
ganz sicher nicht mit einem LDS auf Adresse 0 machen.
>Ja ok liegt definitiv am AVR Studio.
Das gute Studio macht zwar ab und zu mal Ärger, aber C-Code compiliert
es niemals falsch. Garantiert.
Das Studio compiliert nämlich überhaupt keinen C-Code nichts, das macht
der avr-gcc aus dem WinAVR-Paket. Und da wäre die erste Frage:
Welche WinAVR-Version ist installiert?
Und:
Kannst du mal einen vollständigen, kompilierbaren Code anhängen, und
nicht nur Ausschnitte? Dazu das Studio-Projekt-File.
Oliver
Das Studio kompiliert nix, aber es disassembliert sehr wohl. Und um den
Output vom integrierten Disassembler geht es ja offenbar. Wie oben schon
erwähnt zeigt das LSS-File den korrekten Code, WinAVR kommt also nicht
als Schuldiger in Frage.
Nun ja, die beiden gezeigten Disassembler-Beispiele stammen nicht vom
selben Source-Code:
oben:
>45: if (Zeit > 257){ // längere Zeit keine >Pulse
mehr gekommen
weiter unten (aus main.lss)
>if (Zeit > 500){ // längere Zeit (ca 5 sec) keine Pulse >mehr
gekommen
und im oberen Beispiel ist die Disassemblierung auch richtig:
>+0000003F: 91800000 LDS R24,0x0000
Wenn überhaupt, dann ist der Hexcode schon falsch, oder wird falsch
gelesen.
Wo und warum da das Problem auftritt, ist wohl noch nicht so ganz klar.
Oliver
"die beiden gezeigten Disassembler-Beispiele stammen nicht vom
selben Source-Code:"
doch ich habe nur zwischenzeitlich am Code weitergearbeitet und den
vorher willkürlich gewählten Zahlenwert durch denn korrekten ersetzt.
"Wenn überhaupt, dann ist der Hexcode schon falsch, oder wird falsch
gelesen."
der Hexcode ist korrekt, er wird falsch gelesen.
Gruß Rene