Forum: Compiler & IDEs inline assembler


von Hansi (Gast)


Lesenswert?

Hallo,
kann mir mal bitte jemand helfen.
Ich versuch diese drei Zeilen vergeblich als Inline Assembler zu
schreiben. habe schon 1000 Sachen ausprobiert, aber immer meldet der
Compiler irgend einen Fehler

OCR1AL = 0x12;
OCR1AH = 0x12;
PORTA &=  ~(1<<PB1);

Also wer kann mir einen vernünftigen Code sagen??

von leo9@gmx.at (Gast)


Lesenswert?

weil das c-Syntax und keine Assemblerbefehle sind.
#asm
  ldi   rx, 0x12
  out   OCR1AL, rx
  out   OCR1AH, rx
..
..
#endasm
du mußt atürlich noch irgendwo definieren oder includen wer oder was
rx, OCR1AL usw. sind.

grüße leo9

von Hansi (Gast)


Lesenswert?

Ja das ist mir klar das die 3 Zeilen kein ASM sind. Aber jetzt ist mir
klar das ich wohl die definitionen vergessen hatte. Wie mach ich das am
günstigen mit "int r16" und "int OCR1AL" oder muss man register
anders belegen?

von leo9@gmx.at (Gast)


Lesenswert?

#asm
.def  REG_A  = r4
.equ  PORTB  = 0x18
ldi     REG_A, 0x12
out     PORTB, REG_A
..
#endasm

Vorher mußt du aber mit dem Compiler aushandeln dass z.B. r4 dir
"gehört". Für die Definition sind jetzt die GCC-Profis gefragt, in
CodeVision gehts so:
#pragma regalloc-
register unsigned char reg_fuer_asm @4;
Mit Zugriff auf reg_fuer_asm kannst du auch von c aus auf das Byte
zugreifen.
grüße leo9

von OldBug (Gast)


Lesenswert?

Da ich mich selber nocht nicht richtig mit inline-asm für GCC
beschäftigt habe, mir aber der Code von leo9 Falsch vorkommt, verweise
ich hier mal auf die avr-libc-Doku.

http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

Da sollte alles notwednige zu finden sein, vielleicht noch die FAQs
lesen...

von Jörg Wunsch (Gast)


Lesenswert?

Stellt sich allerdings die Frage, warum man sowas überhaupt als inline
asm haben will.

von Hansi (Gast)


Lesenswert?

Das Stückchen soll nur zum Funktionsnachweis dienen, ASM in GCC.
Den Link wend ich mir mal anschauen, danke.

von Jörg Wunsch (Gast)


Lesenswert?

Was willst Du denn als ,,Funktionieren'' hier nachweisen?

Schau Dir mal die Headerdateien unter /usr/[local]/avr/include/avr an
(oder wo auch immer sie auf Windows liegen), ein nicht zu verachtender
Teil der avr-libc ist als inline asm implementiert.  Wenn inline asm
beim GCC kaputt wäre, würde nicht nur die avr-libc unbenutzbar,
sondern wahrscheinlich auch kein einziges Linux dieser Welt mehr
richtig arbeiten.

Nimm also lieber konkrete Projekte, wenn Du sowas machen willst.  Und
denk an den alten Spruch: `Never try to optimize something before
you've profiled it.'  In 99 % der Fälle ist der vom C-Compiler
erzeugte Code irgendwo zwischen ,genügt vollauf' und ,optimal'.

von OldBug (Gast)


Lesenswert?

Ich vermute, es geht Hansi um das "Hello, World!" in inline-ASM für
GCC.
Also so zu sagen ein erstes kennenlernen.
Mir würde sowas zum Beispiel dabei helfen, einen anderen Code mit
inline-ASM zu verstehen.
Das ging bisher bei mir aber auch ohne...

von Jörg Wunsch (Gast)


Lesenswert?

Aber selbst für das ,Hello world' wäre das Lesen und Verstehen der
Makros in den Headerdateien lehrreich genug.

von Hansi (Gast)


Lesenswert?

hallo,

also ich versuche immer noch einen wert in ein register zu schreiben

  asm volatile
  (
    "in r16,0xD7" "\n\t"
    "out %0, %1"
    :"I" (_SFR_MEM_ADDR(OCR1AL))
    :"r16"

  )

so ist der ansatz, aber mit dem %0 und %1 kann ich nicht anfangen.
also es soll der wert 0xd7 in OCR1AL geschrieben werden. das kann doch
nicht so schwierig sein, oder?

von Thomas (Gast)


Lesenswert?

%0 und %1 sind Platzhalter für die hinter den Doppelpunkten angegebenen
Variablen/Register. Die Platzhalter dienen dazu, Werte in einen
Inlineassemblerblock reinzugeben und wieder rauszuholen, sozusagen die
Schnittstelle zwischen dem C Code und dem Assemblercode.

Such mal bei Google nach gcc und inline assembly, da findest du
massenhaft Infos, zum beispiel das hier. Ist zwar über x86, lässt sich
aber auf anderer Prozessoren übertragen:

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

Insbesondere solltest du dir auch Abschnitt 5.3 (Clobber List) zu
Gemüte führen. Dort geht es darum, wie man dem Compiler mitteilt,
welcher Register der Inlineassemblerblock verändert.
Das ist deshalb wichtig, weil der Compiler den Inline Asm Code nicht
analysiert. Wenn du jetzt im Block ein Register änderst, und dem
Compiler das nicht mitteilst, kann es sein, dass dein Code nicht
funktioniert, weil du im Inlineblock ein Register geändert hast,
welches der Compiler für was zur Zeit ganz anderes verwendet.

von Jörg Wunsch (Gast)


Lesenswert?

Warum nicht gleich im inline-assembler-Teil der avr-libc-Doku
nachlesen?

von hansi (Gast)


Lesenswert?

tut mir leid aber ich komme nicht weiter.

kann mir mal bitte jemand wir eine lösung sagen wie ich nun einen wert
z.b 0x34 in eine zählerregister OCR1AL schreibe.

bitte keine verweise auf literatur sondern mal eine lösung bitte. mit
dem GCCAVRinline-assembler-kochbuch versteh ich einige stellen nicht

von Jörg Wunsch (Gast)


Lesenswert?

Du warst doch schon ziemlich nah dran:

void
foo(void)
{
  asm volatile
  (
    "in r16,0xD7" "\n\t"
    "out %0, r16"
    :
    :"I" (_SFR_IO_ADDR(OCR1AL))
    :"r16"
  );
}

Du hast im Wesentlichen nur vergessen, dass die output list ein
Pflichtparameter ist.  Wenn Du nichts zurückgeben lassen willst (also
eine leere Liste hast), musst Du den Doppelpunkt schreiben.  Außerdem
willst Du eine IO-Port-Nummer haben, daher _SFR_IO_ADDR().

Einfacher ist es natürlich, wenn Du _temp_reg_ benutzt, dann
brauchst Du keine clobber list:

  asm volatile
  (
    "in _temp_reg_,0xD7" "\n\t"
    "out %0, __temp_reg__"
    :
    :"I" (_SFR_IO_ADDR(OCR1AL))
  );

Falls Du einen Wert aus dem C-Programm übergeben willst, kannst Du es
gleich dem Compiler überlassen, das Register zu belegen:

#include <stdint.h>
#include <avr/io.h>

void
foo(uint8_t val)
{
  asm volatile
  (
    "out %0, %1"
    :
    :"I" (_SFR_IO_ADDR(OCR1AL)), "r" (val)
  );
}

In diesem Falle würde der Compiler r24 (das das Übergaberegister für
den Funktionsparameter ist) ohne weiteres Umkopieren direkt in der
OUT-Anweisung benutzen.

Aber wie geschrieben: der Aufwand lohnt wirklich nur selten.  Wenn Du
an dem Punkt bist, da Du ganze Funktionen mühevoll mit einer inline
asm Anweisung zusammenzimmern möchtest, solltest Du stattdessen die
Funktion lieber gleich komplett in einer externen Assemblerquelle
ablegen.

von Hansi (Gast)


Lesenswert?

meinst du da das _tmp_reg_  oder ist es egal wie man es nennet?
wenn ich das aber so mit _tmp_reg_ benutze kommt immer eine
fehlermeldung des compilers

C:\DOKUME~1\LOKALE~1\Temp/ccSabaaa.s: Assembler messages:
C:\DOKUME~1\LOKALE~1\Temp/ccSabaaa.s:167: Error: number must be less
than 64

was macht der im temp verzeichnis auf meiner platte?

wenn ich den ersten teil deiner lösung verwende, compiliert er zwar
aber    wenn ich mir die disassembler anzeigen lassen will wurde da
kein code erzeugt.

von Thomas (Gast)


Lesenswert?

> was macht der im temp verzeichnis auf meiner platte?

da werden informationen über dein system gepuffert, die zu einem
späteren zeitpunkt übers netzwerk an microsoft geschickt werden.

spass beiseite, gcc generiert nie direkt objektfiles, das läuft immer
über den assembler, dieses ccSabassirgendwas.s ist der assembler output
von gcc, der jetzt von gas assembliert wird, und wenn du die
dokumentation gelesen hättest, wüsstest du das auch, aber du bevorzugst
ja lösungshinweise ;)

von Jörg Wunsch (Gast)


Lesenswert?

Es muss _temp_reg_ heißen, das ist ein vordefinierter Wert.  Wenn Du
Dir statt des Disassemblers mal den generierten Assemblercode selbst
ansehen würdest (was ich persönlich bei der Benutzung des inline-
Assemblers eigentlich für unverzichtbar halte), dann würdest Du das
auch sehen.

Bei mir ließ sich das Beispiel compilieren.  Guck also in den
asm-Code, warum dort der Assembler der Meinung ist, dass er keine Zahl
kleiner 64 hätte.

von Hansi (Gast)


Lesenswert?

Es ist doch _tmp_reg_ hat ich ja schon mal erwähnt.

>meinst du da das __tmp_reg__<

ich prüf noch mal avr-libc-user-manual dort scheint der inline asm teil
am aktuellsten zu sein

von Jörg Wunsch (Gast)


Lesenswert?

Ja sorry, _tmp_reg_.  Da verschreib ich mich wohl gern mal. :-/

Richtig, das inline asm cookbook in der avr-libc-Doku ist (dank Harald
Kipp, der das mal alles geschrieben hat) auf einem recht guten Stand.

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.