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??
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
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?
#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
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...
Stellt sich allerdings die Frage, warum man sowas überhaupt als inline asm haben will.
Das Stückchen soll nur zum Funktionsnachweis dienen, ASM in GCC. Den Link wend ich mir mal anschauen, danke.
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'.
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...
Aber selbst für das ,Hello world' wäre das Lesen und Verstehen der Makros in den Headerdateien lehrreich genug.
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?
%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.
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
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.
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.
> 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 ;)
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.