Hallo,
ich schreibe meine Programme für meine µC-Projekte normalerweise in der
Arduino-IDE. Das nur vorweg, weil ich weiß, dass hier diesbezüglich ...
nun ... sagen wir mal gewisse "Aversionen" bestehen. Ich habe mich dafür
entschieden, weil ich mich dann im Regelfall nicht um gewisse Aspekte
kümmern muss, wenn ich den µC wechseln will.
Jetzt möchte ich aber -- einfach nur so zum Spaß, einfach nur, weil es
geht -- ein bischen inline-assembler verwenden. Was mir beim gcc-avr
dabei unklar ist und was ich in den tutorials dazu auch bisher nicht
finden konnte, ist folgendes: Wie übergebe ich bei Inline-Assembly mehr
als drei Speicherstellen?
1
// mit maximal drei Speicherstellen klappt's...
2
3
int16_tsomeCppFunc()
4
{
5
int8_tvar1=0;
6
int8_tvar2=0;
7
int8_tvar3=0;
8
int16_tresult=0;
9
10
asmvolatile
11
(
12
"..."// random assembly code here...
13
:[result](=r)(result)
14
:[var1](x)(var1),
15
[var2](y)(var2),
16
[var3](z)(var3)
17
);
18
}
19
20
// was mache ich mit mehr zu übergebenden Variablen?
21
// Insbesondere, weil es sich um einen C++-Compiler handelt, d.h. die
22
// Symbolnamen sind ja normalerweise "gemangled"...
23
24
int16_tsomeOtherCppFunc()
25
{
26
int8_tvar1=0;
27
int8_tvar2=0;
28
int8_tvar3=0;
29
int8_tvar4=0;
30
int8_tvar5=0;
31
int16_tresult=0;
32
33
asmvolatile
34
(
35
"..."// random assembly code here...
36
:[result](=r)(result)
37
:[var1](x)(var1),
38
[var2](y)(var2),
39
[var3](z)(var3),
40
???undnun???
41
);
42
}
Vielleicht findet sich jemand, der mir das Brett vor'm Kopf wegschrauben
kann?
danke schon mal,
L
Warum schreibst du die Variablen denn in die Pointer-Registerpaare? Du
kannst da auch einfach r angeben, dann wird automatisch ein Register
zugewiesen.
Die Adressen dürften bei der Kiste aus zwei Bytes bestehen... das passt
doch nicht in ein Register?! Oder nimmt der gcc dann immer ein
Register-Pärchen? Also z.B. r15+r16 für eine Adresse? Ich benötige die
Adresse der Variable... nicht den Inhalt...
best
L
Ich sehe gerade, dass ich tippfauler mensch die "&" vergessen habe...
Also ich habe dort ein ganzes "Büschel" von Variablen int8_t und int16_t
und die muss ich alle irgendwie da übergeben... Ich sehe aber, dass mein
Pseudo-Code nicht gerade optimal war...
best
L
Ich versuche es einmal anders...
ich habe ein ganzes Büschel von Variablen. Von diesen benötige ich die
Adressen im inline-assembly-block. Und daran scheitere ich... ein
kleines Beispiel wäre schön... direkter Zugriff über die Variablennamen
geht ja nicht...
Stefan schrieb:> Die Adressen dürften bei der Kiste aus zwei Bytes bestehen...
Ja, aber du übergibst keine Adressen.
> das passt doch nicht in ein Register?! Oder nimmt der gcc dann immer ein> Register-Pärchen? Also z.B. r15+r16 für eine Adresse? Ich benötige die> Adresse der Variable... nicht den Inhalt...
Warum? Damit zwingst du den Compiler, die Variablen in den Speicher zu
schreiben. Außerdem ist die Zahl der Pointer-Register nunmal begrenzt,
wie du merkst, und du brauchst die immer paarweise. Du kannst natürlich
die anderen Adressen in andere Register schreiben und dann in deinem
Inline-Assembler zum Zugriff ins Pointer-Register kopieren. Oder du
teilst deinen Assembler-Block in mehrere auf. Als letztes würde mir noch
einfallen, die Zeiger alle in ein Array zu stecken und dessen Adresse an
deinen Assembler-Block zu übergeben.
Rolf M. schrieb:> Warum? Damit zwingst du den Compiler, die Variablen in den Speicher zu> schreiben
Die Variablen stehen schon im Speicher. Sie sind als static ints
deklariert, damit sie zwischen zwei Aufrufen der Funktion erhalten
bleiben. Read->Modify->Write.
Ich will wirklich die Adresse und nicht den Inhalt... ("normalerweise"
würde ich/man das nicht wollen, da hast du schon recht. Aber in diesem
speziellen Fall will ich wirklich die Adresse. Und ja, mein initialer
Pseudo-Code-Schnippsel war fehlerhaft in der Beziehung)...
L
Stefan schrieb:> weil ich mich dann im Regelfall nicht um gewisse Aspekte> kümmern muss, wenn ich den µC wechseln will.Stefan schrieb:> Jetzt möchte ich aber -- einfach nur so zum Spaß, einfach nur, weil es> geht -- ein bischen inline-assembler verwenden.
Das ist wie Feuer und Wasser.
Erst willst Du flexibel sein und dann wieder absichtlich Abhängigkeiten
reinbasteln.
Viel Spaß z.B. bei Hardwareregistern, die mal im IO und mal im MEM
liegen.
Auch mußt Du auf den Compiler Rücksicht nehmen, also PUSH/POP bis der
Arzt kommt. Der Compiler merkt ja nicht, wenn Du ihm Register
verstellst.
Assembler nimmt man nicht ohne wirklich äußerst große Not.
Peter D. schrieb:> Das ist wie Feuer und Wasser.> Erst willst Du flexibel sein und dann wieder absichtlich Abhängigkeiten> reinbasteln.
Nun ich denke er möchte das nur zu Lernzwecken machen. Und das hat mich
gerade gefreut. Trotz Arduino-IDE ;)
Stefan schrieb:> Danke, habe es inzwischen selbst herausgefunden.
Wie hast du es denn gelöst? Es könnte ja sein, dass da noch jemand
dieses Problem hat und dann kann er die Lösung hier finden.
Wenn man mehr braucht als die Register hergeben, braucht man halt einen
Stack. Den kann man ja auch vorher selbst basteln.
Aber ich glaube auch, dass man vorher ein paar andere Fingerübungen
gemacht haben sollte.
Stefan schrieb:> wie übergebe ich bei Inline-Assembly mehr> als drei Speicherstellen?
Der Fall kommt in der Praxis nie vor.
Bei mehr als 3 Pointern dürfte der C-Optimizer vom GCC dem Menschen
überlegen sein. Lies: Mann schreibt das Ganze in C und lässt den
Assembler weg.
Hintergrund ist dass der AVR IIRC nur über die X,Y,Z Register indirekte
Speicherzugriffe machen kann. D.h. man müsste dann umständlich mit Stack
oder weiteren Registern hantieren.
Der C-optimizer kann jedoch mitbekommen dass eine oder mehrere dieser
Pointer auf feste RAM Adressen zeigen und dann die indirekte durch
direkte Addressierung ersetzen.
Man kann aber auch Assember und C-Objekte zusammen linken.
Dazu schreibt man sich in C einen Rumpf, der die gewünschten Typen an
globalen Variablen, Argumenten und Returnwerten benutzt und übersetzt
ihn nach Assembler (*.S). Nun kann man dort den gewünschten
Assemblercode einfügen ohne irgendwelche unleserliche Syntax.
Daß auf Assembler keinerlei Optimierungen vorgenommen werden, dürfte
klar sein.