www.mikrocontroller.net

Forum: Compiler & IDEs inline assembler


Autor: Hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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??

Autor: leo9@gmx.at (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: leo9@gmx.at (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Hansi (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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'.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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-Assemb...

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.

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.