Forum: Compiler & IDEs mehr als drei Speicherstellen bei inline-assembly (avr-gcc)


von Stefan (Gast)


Lesenswert?

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_t someCppFunc()
4
{
5
    int8_t var1 = 0;
6
    int8_t var2 = 0;
7
    int8_t var3 = 0;
8
    int16_t result = 0;
9
10
    asm volatile
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_t someOtherCppFunc()
25
{
26
    int8_t var1 = 0;
27
    int8_t var2 = 0;
28
    int8_t var3 = 0;
29
    int8_t var4 = 0;
30
    int8_t var5 = 0;
31
    int16_t result = 0;
32
33
    asm volatile
34
    (
35
        "..."  // random assembly code here...
36
        : [result] (=r) (result)
37
        : [var1] (x) (var1),
38
          [var2] (y) (var2),
39
          [var3] (z) (var3),
40
          ??? und nun ???
41
    );
42
}

Vielleicht findet sich jemand, der mir das Brett vor'm Kopf wegschrauben 
kann?

danke schon mal,
L

von Rolf M. (rmagnus)


Lesenswert?

Warum schreibst du die Variablen denn in die Pointer-Registerpaare? Du 
kannst da auch einfach r angeben, dann wird automatisch ein Register 
zugewiesen.

von Stefan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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...

von Rolf M. (rmagnus)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

Danke, habe es inzwischen selbst herausgefunden.

von Peter D. (peda)


Lesenswert?

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.

von 900ss (900ss)


Lesenswert?

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.

von Nico T. (wurstnase)


Lesenswert?

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.

von Jim M. (turboj)


Lesenswert?

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.

Beitrag #6627900 wurde von einem Moderator gelöscht.
Beitrag #6627956 wurde von einem Moderator gelöscht.
von Peter D. (peda)


Lesenswert?

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.

Beitrag #6630062 wurde von einem Moderator gelöscht.
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.