Guten Tag! Ich habe eine Frage bzg. Macro in AVR-Assembler. Um Macro unabhängig von Adresse zu machen, verwendet man Schreibweise: [asm] .macro outi ; @0 Ziel, @1 Data, r24 wird benutzt ldi r24, @1 .if @0 < 0x40 out @0, r24 .else sts @0, r24 .endif .endm [/asm] Leider arbeitet das mit Registernummer nicht. Solche Variante: [asm] .macro ldi8x ; @0 Reg, @1 Data8 .if @0 > 15 ldi @0,@1 .else ldi r24,@1 mov @0,r24 .endif .endm [/asm] wird als error erkannt: error: syntax error, unexpected REGISTER Wenn statt .if @0 > 15 .if @0 > r15 zu schreiben, ändert sich nichts. Die Frage: gibt es eine Möglichkeit, Macro für Arbeit mit Register unabhängig von Registernummer zu schreiben? Vielen Dank im voraus P.S. bisher habe ich nur eine Möglichkeit gefunden, aber sie sieht nicht so schön aus. Vielleicht gibt es bessere Varianten? Gefundene Möglichkeit: [asm] .equ REG0 = 0 .equ REG1 = 1 .equ REG2 = 2 .equ REG3 = 3 .equ REG4 = 4 .equ REG5 = 5 .equ REG6 = 6 .equ REG7 = 7 .equ REG8 = 8 .equ REG9 = 9 .equ REG10 = 10 .equ REG11 = 11 .equ REG12 = 12 .equ REG13 = 13 .equ REG14 = 14 .equ REG15 = 15 .equ REG16 = 16 .equ REG17 = 17 .equ REG18 = 18 .equ REG19 = 19 .equ REG20 = 20 .equ REG21 = 21 .equ REG22 = 22 .equ REG23 = 23 .equ REG24 = 24 .equ REG25 = 25 .equ REG26 = 26 .equ REG27 = 27 .equ REG28 = 28 .equ REG29 = 29 .equ REG30 = 30 .equ REG31 = 31 .macro ldi8x ; @0 REG_Nr, @1 Data8 .if @0 == 0 ldi r24,@1 mov r0,r24 .elif @0 == 1 ldi r24,@1 mov r1,r24 .elif @0 == 2 ldi r24,@1 mov r2,r24 .elif @0 == 3 ldi r24,@1 mov r3,r24 .elif @0 == 4 ldi r24,@1 mov r4,r24 .elif @0 == 5 ldi r24,@1 mov r5,r24 .elif @0 == 6 ldi r24,@1 mov r6,r24 .elif @0 == 7 ldi r24,@1 mov r7,r24 .elif @0 == 8 ldi r24,@1 mov r8,r24 .elif @0 == 9 ldi r24,@1 mov r9,r24 .elif @0 == 10 ldi r24,@1 mov r10,r24 .elif @0 == 11 ldi r24,@1 mov r11,r24 .elif @0 == 12 ldi r24,@1 mov r12,r24 .elif @0 == 13 ldi r24,@1 mov r13,r24 .elif @0 == 14 ldi r24,@1 mov r14,r24 .elif @0 == 15 ldi r24,@1 mov r15,r24 .elif @0 == 16 ldi r16,@1 .elif @0 == 17 ldi r17,@1 .elif @0 == 18 ldi r18,@1 .elif @0 == 19 ldi r19,@1 .elif @0 == 20 ldi r20,@1 .elif @0 == 21 ldi r21,@1 .elif @0 == 22 ldi r22,@1 .elif @0 == 23 ldi r23,@1 .elif @0 == 24 ldi r24,@1 .elif @0 == 25 ldi r25,@1 .elif @0 == 26 ldi r26,@1 .elif @0 == 27 ldi r27,@1 .elif @0 == 28 ldi r28,@1 .elif @0 == 29 ldi r29,@1 .elif @0 == 30 ldi r30,@1 .elif @0 == 31 ldi r31,@1 .endif .endm ldi8x REG15,5 [/asm]
:
Schau mal hier: Beitrag "AVR Assembler, Macro, Conditional mit Register" Vielleicht kannst Du was draus übernehmen.
Danke. Leider fand ich dort nichts Neues für mich. Auch keine Lösung, wie man Registernummer als .if-Parameter verwenden kann (nur etwa wie ich schon gemacht habe). Na gut, vielleicht gibt es eine andere Lösung gar nicht. Vielleicht darf ich noch eine Frage stellen: Allgemein wird oft gesagt: man kann für ein Register mehrere .def machen. In Praxis kommt aber immer Warning. Wenn viele nicht sinnvollen Warnings kommen, kann man vielleicht was Wichtiges nicht merken. Da in Dateien von Mikrocontroller so wie m644PAdef.inc die Register r26-r31 schon als XYZ definiert sind, kann man für diese Register keine defs mehr machen. Auch Beispiele von Atmel selbst (so wie APPLICATION NOTE AVR200 ) geben Warning. Warscheinlich kann man Warnings bzg. mehrfachen .defs irgendwo abschalten. Aber wie genau macht man das?
:
Bearbeitet durch User
Zur ursprünglichen Frage (avrasm2):
1 | .macro ldi8x ; @0 Reg, @1 Data8 |
2 | .if @0 > 15 |
3 | ldi r@0,@1 |
4 | .else |
5 | ldi r24,@1 |
6 | mov r@0,r24 |
7 | .endif |
8 | .endm |
9 | |
10 | ldi8x 9,'S' |
11 | ldi8x 21,'S' |
Zur zweiten: eventuell #define verwenden.
>Allgemein wird oft gesagt: man kann für ein Register mehrere .def >machen. In Praxis kommt aber immer Warning. "undef" verwenden?
1 | .def accu = r16 |
2 | .undef accu |
3 | .def count = r16 |
4 | .undef count |
5 | .def sensor = r16 |
Leider gibt Variante
1 | .macro ldi8x ; @0 reg, @1 Data8 |
2 | .if @0 > 15 |
3 | ldi r@0,@1 |
4 | .else |
5 | ldi r24,@1 |
6 | mov r@0,r24 |
7 | .endif |
8 | .endm |
9 | |
10 | ldi8x r15,5 |
11 | ldi8x r16,9 |
auch error: syntax error, unexpected REGISTER Kann ich mit #define bestimmte Warning ausschalten?
LostInMusic schrieb: > "undef" verwenden? Das bringt nichts: so kann man entweder Eines oder Anderes verwenden. In avr200.asm steht aber:
1 | .def mc8u =r16 ;multiplicand |
2 | .def mp8u =r17 ;multiplier |
3 | .def m8uL =r17 ;result Low byte |
4 | .def m8uH =r18 ;result High byte |
5 | .def mcnt8u =r19 ;loop counter |
Komisch, daß selbst der Entwickler von AVR Beispielcode gibt, der die Warnings auslöst. warning: Register r17 already defined by the .DEF directive
:
Bearbeitet durch User
Maxim B. schrieb: > Leider fand ich dort nichts Neues für mich. Auch keine Lösung, wie man > Registernummer als .if-Parameter verwenden kann (nur etwa wie ich schon > gemacht habe). Dann bist du blöd, denn genau so eine Lösung wurde im Thread gepostet, nämlich von mir.
c-hater schrieb: > Dann bist du blöd, denn genau so eine Lösung wurde im Thread gepostet, > nämlich von mir. Meinst du das?
1 | .macro fetch_byte |
2 | .set r16_macroprobe = 0 |
3 | .set @0_macroprobe = 1 |
4 | .if r16_macroprobe |
5 | rcall read_byte |
6 | .else |
7 | push r16 |
8 | rcall read_byte |
9 | mov @0,r16 |
10 | pop r16 |
11 | .endif |
12 | .endm |
D.h. du stellst r16_macroprobe in Null und gleich danach prüfst mit .if, ob r16_macroprobe doch zufällig nicht Eins wird? Deinen Humor verstehe ich schlecht...
Also manchmal ... !-? Maxim B. schrieb: > Leider gibt Variante.macro ldi8x ; @0 reg, @1 Data8 > ldi8x r15,5 > ldi8x r16,9 > auch error: syntax error, unexpected REGISTER S. Landolt schrieb: > ldi8x 9,'S' > ldi8x 21,'S'
Maxim B. schrieb: > D.h. du stellst r16_macroprobe in Null und gleich danach prüfst mit .if, > ob r16_macroprobe doch zufällig nicht Eins wird? Ganz genau. Das passiert nämlich nur genau dann, wenn tatsächlich r16 als Parameter an das Makro übergeben wurde. > Deinen Humor verstehe > ich schlecht... Das hat mit Humor nix zu schaffen. Es ist nur die einfachste Möglichkeit, diese Funktion mit dem AVR-Assembler zu realisieren.
> Kann ich mit #define bestimmte Warning ausschalten?
So ungefähr - es erlaubt zum Beispiel Folgendes ohne Warnung:
1 | #define hinz r30 |
2 | #define kunz ZL |
3 | ldi ZL,45 |
4 | ldi hinz,67 |
5 | ldi kunz,89 |
Und haben Sie endlich Ihre überflüssigen 'r' im Macro-Aufruf entdeckt?
Zu "in/out unabhängig von Adresse" empfehle ich "application note AVR001 - Conditional Assembly" (Include-Datei hängt an). Die Atmel-Originaldatei hieß "macros.inc". Ich habe gegenüber dem Original die übliche Prep-Pro.-Mimik hinzugefügt, damit mehrfaches Include geht. AVRASM .if geht nur mit Zahlen. AVRASM hat keine Stringfunktionen außer "strlen". In Makros geht immerhin "zusammenkleben". r@0 wurde ja schon geschrieben. "undef" wurde schon genannt. Wie geschrieben, werden xl, xh, ... in den Dateien wie m644PAdef.inc per .def definiert. Diese Definitionen kann man aber selbst gleich nach dem .include per .undef aufheben, wenn man den Registern selbst Namen gehen möchte und Warnungen vermeiden will. x, y und z scheinen dagegen in AVRASM fest "verdrahtet" zu sein.
> x, y und z scheinen dagegen in AVRASM fest "verdrahtet" zu sein.
Auch daran lässt sich mit #define vorbeikommen:
1 | #define Zeiger z |
2 | ldd r16,Zeiger+12 |
Thomas R. schrieb: > AVRASM .if geht nur mit Zahlen. Genau. Das .if zwingt den Assembler, die bis dahin reine Textersetzung zu evaluieren, d.h.: tatsächlich Werte auszurechnen. > AVRASM hat keine Stringfunktionen außer > "strlen". In Makros geht immerhin "zusammenkleben". Also letztlich nicht viel anders als z.B. beim C-Präprozessor (der übrigens zusätzlich zum "nativen" ebenfalls im AVR-Assembler verfügbar ist). Das Einzige, was tatsächlich fehlt, ist die "stringification" von Zahlen, also so ziemlich das Umgekehrte von dem, was bei der Auswertung bei .if passiert. > x, y und z scheinen dagegen in AVRASM fest "verdrahtet" zu sein. Sind sie, wenn man sie als Adressierungsangabe für einen Opcode verwendet. Also kann man (mittels Präprozessor-Textersetzung) auch darum herumlavieren und z.B. so ein Codestück (assemblierbar und lauffähig) produzieren: ldi DPTRL, Low(FlashAddr) ldi DPTRH, High(FlashAddr lpm r0, DPTR+ Der dafür nötige deklarativen Vorspann sieht so aus: .UNDEF ZL .UNDEF ZH .DEF DPTRL = R30 .DEF DPTRH = R31 #define DPTR Z Wahnsinn. Mit dieser Source-Warze könnte man auch gleich in C programieren. Das sieht zwar anders aus, besteht aber weit überwiegend aus genau solchen deklarativen Geschwüren ohne jeden sinnvollen Beitrag zum Code...
Auch wenn ich mich jetzt als großer nerd outen sollte, stelle ich mal die Frage, warum ich ich das wollen sollte... Maxim B. schrieb: > Die Frage: gibt es eine Möglichkeit, Macro für Arbeit mit Register > unabhängig von Registernummer zu schreiben? Wie c-hater, für mich schon richtig, bemerkt hat, geht dieser Wunsch doch in eine Richtung, die man "mit assembler" überhaupt nicht haben will. Ich entscheide, was ich mit @0 meine und da brauche ich doch keine weitere "funktionale Zuordnung"! Aber wie gesagt, ich könnte das Problem auch einfach nicht verstanden haben. Gruß Rainer
Rainer V. schrieb: > Wie c-hater, für mich schon richtig, bemerkt hat, geht dieser Wunsch > doch in eine Richtung, die man "mit assembler" überhaupt nicht haben > will. Das ist nicht ganz der Punkt. Der vergleichsweise Luxus von C wäre schon an vielen Stellen durchaus schick (unter Inkaufnahme der aufgeblähten Syntax, die aber letztlich erst den Luxus möglich macht). Die Sache ist: wenn man sich bewußt (aus welchen Gründen auch immer) dafür entschieden hat, in Asm zu entwickeln, muss man sicher nicht seine Zeit damit vertrödeln, irgendwelche Macros zu bauen, deren Aufgabe einzig ist, dass es "fast" wie C benutzbar wird. Das ist absoluter Schwachsinn. Das kann C selber viel besser, indem man einfach wirklich gleich in C schreibt. C ist de facto schließlich der hochentwickeltste Macro-Assembler aller Zeiten. Jedenfalls für sehr viele Architekturen. Nö, man übernimmt das C-Sprachkonzept nur soweit, wie sinnvoll (also insbesondere: noch nicht störend) ist und man ignoriert alle Konventionen der C-Runtime). Das zusammen macht den Trick. So kann man einerseits les- und wartbare Asm-Programme schreiben, andererseits aber enorme Performance-Vorteile erreichen.
Ja, c-h, aber der Luxus ist letztlich doch auch mein Ding nicht. Ich will doch über Makros keine "Hochsprachen-Funktionen" in mein bescheidenes Programm holen. Mit Makros mache ich eine klitzekleine Vereinbarung, die fast nichts macht, aber vielleicht oft gebraucht wird, und deshalb einfach nicht 1000-mal getippt werden möcht...ok? Gruß Rainer
Rainer V. schrieb: > Ja, c-h, aber der Luxus ist letztlich doch auch mein Ding nicht. Ich > will doch über Makros keine "Hochsprachen-Funktionen" in mein > bescheidenes Programm holen. Mit Makros mache ich eine klitzekleine > Vereinbarung, die fast nichts macht, aber vielleicht oft gebraucht wird, > und deshalb einfach nicht 1000-mal getippt werden möcht...ok? Was was genau ist daran deiner Meinung nach qualitativ anders als am Grundkonzept von C? Nö, der Unterschied ist einfach nur quantitativ. Etwa: Was an Performance bin ich bereit zu opfern, um meine mühsam erstellten Macros benutzen zu können. Das fällt in Asm schlicht viel leichter, weil man typisch nicht so viele vorgefertigte Macros hat (oder sie zumindest leichter anpassen/erweitern kann, weil sie eigenes Werk und nicht tief und quasi unveränderlich im Compiler mit Abhängigkeit zur Runtime begraben sind)...
S. Landolt schrieb: > Und haben Sie endlich Ihre überflüssigen 'r' im Macro-Aufruf entdeckt? Ich habe Sie falsch verstanden. Ich dachte, Sie sagten, ich muß r@0 schreiben. Ich selber wollte statt r0-r31 @0 usw, somit wären Varianten wie @0+4 möglich. Z.B.:
1 | .macro ldix8 |
2 | .if @0>15 |
3 | ldi @0,@1 |
4 | .else |
5 | ldi r16,@1 |
6 | mov @0,r16 |
7 | .endm |
8 | |
9 | .macro ldix16 |
10 | ldix8 @0,low(@1) |
11 | ldix8 @0+1,high(@1) |
12 | .endm |
13 | |
14 | .macro ldix32 |
15 | ldix16 @0,(@1)&&0xffff |
16 | ldix16 @0+2,((@1)>>16)&&0xffff |
17 | .endm |
18 | |
19 | ldix32 r14,0xf1c2658a |
Wenn ich aber absolute Adresse von Register schreiben muß, wo habe ich Gewinn? Mein Wunsch wäre, daß in Macro Unterschied zwischen r0-r15 und r16-r31 erkannt wird, so daß ich gewöhnliche Syntax mit Register verwenden könnte. Meine Variante mit REG0-REG31 macht @+x möglich, Preis dafür ist aber, daß ich statt r0-r31 REG0-REG31 schreiben muß. Das gefällt mir nicht. S. Landolt schrieb: > So ungefähr - es erlaubt zum Beispiel Folgendes ohne Warnung:#define > hinz r30 > #define kunz ZL > ldi ZL,45 > ldi hinz,67 > ldi kunz,89 Danke! Ich werde das gleich ausprobieren. Thomas R. schrieb: > Zu "in/out unabhängig von Adresse" empfehle ich "application note AVR001 > - Conditional Assembly" (Include-Datei hängt an). Die > Atmel-Originaldatei hieß "macros.inc". Ich habe gegenüber dem Original > die übliche Prep-Pro.-Mimik hinzugefügt, damit mehrfaches Include geht. > > AVRASM .if geht nur mit Zahlen. AVRASM hat keine Stringfunktionen außer > "strlen". In Makros geht immerhin "zusammenkleben". r@0 wurde ja schon > geschrieben. Danke für die Erklärung! Ich werde das alles versuchen. Rainer V. schrieb: > für mich schon richtig, bemerkt hat, geht dieser Wunsch > doch in eine Richtung, die man "mit assembler" überhaupt nicht haben > will. Ich entscheide, was ich mit @0 meine Assembler hat auch Vorteile gegen C. In Assembler wird gemacht, wie ich will. In C wird alles vom Compiler entschieden. Manchmal kostet viel Zeil, zu erreichen, daß notwendige Sachen nicht wegoptimiert werden und trotzdem effiziente Code kommt. Manchmal nervt mich selbst Gedanke, daß eine Maschine mir Menschen etwas vorschreiben will.
:
Bearbeitet durch User
c-hater schrieb: > Ganz genau. Das passiert nämlich nur genau dann, wenn tatsächlich r16 > als Parameter an das Makro übergeben wurde. Danke!!! Das arbeitet! Ich verstehe zwar nicht, wie, aber das arbeitet :)
1 | .macro ldix8 |
2 | .set r16_macroprobe = 0 |
3 | .set r17_macroprobe = 0 |
4 | .set r18_macroprobe = 0 |
5 | .set r19_macroprobe = 0 |
6 | .set r20_macroprobe = 0 |
7 | .set r21_macroprobe = 0 |
8 | .set r22_macroprobe = 0 |
9 | .set r23_macroprobe = 0 |
10 | .set r24_macroprobe = 0 |
11 | .set r25_macroprobe = 0 |
12 | .set r26_macroprobe = 0 |
13 | .set r27_macroprobe = 0 |
14 | .set r28_macroprobe = 0 |
15 | .set r29_macroprobe = 0 |
16 | .set r30_macroprobe = 0 |
17 | .set r31_macroprobe = 0 |
18 | .set @0_macroprobe = 1 |
19 | .if r16_macroprobe |
20 | ldi @0,@1 |
21 | .elif r17_macroprobe |
22 | ldi @0,@1 |
23 | .elif r18_macroprobe |
24 | ldi @0,@1 |
25 | .elif r19_macroprobe |
26 | ldi @0,@1 |
27 | .elif r20_macroprobe |
28 | ldi @0,@1 |
29 | .elif r21_macroprobe |
30 | ldi @0,@1 |
31 | .elif r22_macroprobe |
32 | ldi @0,@1 |
33 | .elif r23_macroprobe |
34 | ldi @0,@1 |
35 | .elif r24_macroprobe |
36 | ldi @0,@1 |
37 | .elif r25_macroprobe |
38 | ldi @0,@1 |
39 | .elif r26_macroprobe |
40 | ldi @0,@1 |
41 | .elif r27_macroprobe |
42 | ldi @0,@1 |
43 | .elif r28_macroprobe |
44 | ldi @0,@1 |
45 | .elif r29_macroprobe |
46 | ldi @0,@1 |
47 | .elif r30_macroprobe |
48 | ldi @0,@1 |
49 | .elif r31_macroprobe |
50 | ldi @0,@1 |
51 | .else |
52 | ldi r16,@1 |
53 | mov @0,r16 |
54 | .endif |
55 | .endm |
56 | |
57 | |
58 | start: |
59 | nop |
60 | ldix8 r15,5 |
61 | ldix8 r16,6 |
62 | ldix8 r17,7 |
63 | ldix8 r2,0x23 |
64 | ldix8 r5,0xfd |
65 | ldix8 r24,0xaa |
66 | ldix8 r16,0x11 |
67 | ldix8 r22,0x88 |
68 | rjmp start |
:
Bearbeitet durch User
> Danke!!! Das arbeitet! Aha, interessant - und wie funktioniert nun das von Ihnen verlangte > ldix32 r14,0xf1c2658a d.h. das automatische Hochzählen von Registernummern?
PS: Denn ldix8 alleine hat schließlich auch in der von mir vorgeschlagenen Macro-Version funktioniert.
Ich mache jetzt verschiedene Proben. Eine Variante ermöglich indirekte Register nicht, dafür aber "natürliche" Syntax. Andere Variante umgekehrt, unnatürlichen Syntax, aber indirekte Register :)
1 | .macro setr16 |
2 | .set r16_macroprobe = 0 |
3 | .set r17_macroprobe = 0 |
4 | .set r18_macroprobe = 0 |
5 | .set r19_macroprobe = 0 |
6 | .set r20_macroprobe = 0 |
7 | .set r21_macroprobe = 0 |
8 | .set r22_macroprobe = 0 |
9 | .set r23_macroprobe = 0 |
10 | .set r24_macroprobe = 0 |
11 | .set r25_macroprobe = 0 |
12 | .set r26_macroprobe = 0 |
13 | .set r27_macroprobe = 0 |
14 | .set r28_macroprobe = 0 |
15 | .set r29_macroprobe = 0 |
16 | .set r30_macroprobe = 0 |
17 | .set r31_macroprobe = 0 |
18 | .endm |
19 | |
20 | .macro ldireg ; @0 r0-r31, @1 Data8, 1-2c |
21 | ; Beispiel: ldireg r15,25 |
22 | ; wenn r0-r15, r16 benutzt |
23 | setr16 |
24 | .set @0_macroprobe = 1 |
25 | |
26 | .if r16_macroprobe |
27 | ldi @0,@1 |
28 | .elif r17_macroprobe |
29 | ldi @0,@1 |
30 | .elif r18_macroprobe |
31 | ldi @0,@1 |
32 | .elif r19_macroprobe |
33 | ldi @0,@1 |
34 | .elif r20_macroprobe |
35 | ldi @0,@1 |
36 | .elif r21_macroprobe |
37 | ldi @0,@1 |
38 | .elif r22_macroprobe |
39 | ldi @0,@1 |
40 | .elif r23_macroprobe |
41 | ldi @0,@1 |
42 | .elif r24_macroprobe |
43 | ldi @0,@1 |
44 | .elif r25_macroprobe |
45 | ldi @0,@1 |
46 | .elif r26_macroprobe |
47 | ldi @0,@1 |
48 | .elif r27_macroprobe |
49 | ldi @0,@1 |
50 | .elif r28_macroprobe |
51 | ldi @0,@1 |
52 | .elif r29_macroprobe |
53 | ldi @0,@1 |
54 | .elif r30_macroprobe |
55 | ldi @0,@1 |
56 | .elif r31_macroprobe |
57 | ldi @0,@1 |
58 | .else |
59 | ldi r16,@1 |
60 | mov @0,r16 |
61 | .endif |
62 | .endm |
63 | |
64 | .macro exorireg ; @0 r0-r31, @1 Data8, 2c, wenn r16, 6c |
65 | ; Beispiel: exorireg r15,25 |
66 | ; r16 benutzt |
67 | .set r16_macroprobe = 0 |
68 | .set @0_macroprobe = 1 |
69 | .if r16_macroprobe |
70 | push r17 |
71 | ldi r17,@1 |
72 | eor r16,r17 |
73 | pop r17 |
74 | .else |
75 | ldi r16,@1 |
76 | eor @0,r16 |
77 | .endif |
78 | .endm |
79 | |
80 | ldireg r5,18 |
81 | ldireg r18,6 |
82 | exorireg r18,2 |
1 | .equ REG0 = 0 |
2 | .equ REG1 = 1 |
3 | .equ REG2 = 2 |
4 | .equ REG3 = 3 |
5 | .equ REG4 = 4 |
6 | .equ REG5 = 5 |
7 | .equ REG6 = 6 |
8 | .equ REG7 = 7 |
9 | .equ REG8 = 8 |
10 | .equ REG9 = 9 |
11 | .equ REG10 = 10 |
12 | .equ REG11 = 11 |
13 | .equ REG12 = 12 |
14 | .equ REG13 = 13 |
15 | .equ REG14 = 14 |
16 | .equ REG15 = 15 |
17 | .equ REG16 = 16 |
18 | .equ REG17 = 17 |
19 | .equ REG18 = 18 |
20 | .equ REG19 = 19 |
21 | .equ REG20 = 20 |
22 | .equ REG21 = 21 |
23 | .equ REG22 = 22 |
24 | .equ REG23 = 23 |
25 | .equ REG24 = 24 |
26 | .equ REG25 = 25 |
27 | .equ REG26 = 26 |
28 | .equ REG27 = 27 |
29 | .equ REG28 = 28 |
30 | .equ REG29 = 29 |
31 | .equ REG30 = 30 |
32 | .equ REG31 = 31 |
33 | |
34 | .macro ldi8_x ; @0 REG_Nr, @1 Data8, r16 benutzt |
35 | .if @0 == 0 |
36 | ldi r16,@1 |
37 | mov r0,r16 |
38 | .elif @0 == 1 |
39 | ldi r16,@1 |
40 | mov r1,r16 |
41 | .elif @0 == 2 |
42 | ldi r16,@1 |
43 | mov r2,r16 |
44 | .elif @0 == 3 |
45 | ldi r16,@1 |
46 | mov r3,r16 |
47 | .elif @0 == 4 |
48 | ldi r16,@1 |
49 | mov r4,r16 |
50 | .elif @0 == 5 |
51 | ldi r16,@1 |
52 | mov r5,r16 |
53 | .elif @0 == 6 |
54 | ldi r16,@1 |
55 | mov r6,r16 |
56 | .elif @0 == 7 |
57 | ldi r16,@1 |
58 | mov r7,r16 |
59 | .elif @0 == 8 |
60 | ldi r16,@1 |
61 | mov r8,r16 |
62 | .elif @0 == 9 |
63 | ldi r16,@1 |
64 | mov r9,r16 |
65 | .elif @0 == 10 |
66 | ldi r16,@1 |
67 | mov r10,r16 |
68 | .elif @0 == 11 |
69 | ldi r16,@1 |
70 | mov r11,r16 |
71 | .elif @0 == 12 |
72 | ldi r16,@1 |
73 | mov r12,r16 |
74 | .elif @0 == 13 |
75 | ldi r16,@1 |
76 | mov r13,r16 |
77 | .elif @0 == 14 |
78 | ldi r16,@1 |
79 | mov r14,r16 |
80 | .elif @0 == 15 |
81 | ldi r16,@1 |
82 | mov r15,r16 |
83 | .elif @0 == 16 |
84 | ldi r16,@1 |
85 | .elif @0 == 17 |
86 | ldi r17,@1 |
87 | .elif @0 == 18 |
88 | ldi r18,@1 |
89 | .elif @0 == 19 |
90 | ldi r19,@1 |
91 | .elif @0 == 20 |
92 | ldi r20,@1 |
93 | .elif @0 == 21 |
94 | ldi r21,@1 |
95 | .elif @0 == 22 |
96 | ldi r22,@1 |
97 | .elif @0 == 23 |
98 | ldi r23,@1 |
99 | .elif @0 == 24 |
100 | ldi r24,@1 |
101 | .elif @0 == 25 |
102 | ldi r25,@1 |
103 | .elif @0 == 26 |
104 | ldi r26,@1 |
105 | .elif @0 == 27 |
106 | ldi r27,@1 |
107 | .elif @0 == 28 |
108 | ldi r28,@1 |
109 | .elif @0 == 29 |
110 | ldi r29,@1 |
111 | .elif @0 == 30 |
112 | ldi r30,@1 |
113 | .elif @0 == 31 |
114 | ldi r31,@1 |
115 | .endif |
116 | .endm |
117 | |
118 | .macro ldi8x ; @0 REG, @1 Data8 1 oder 2 c |
119 | ; wenn REG 0...15, r16 benutzt |
120 | ldi8_x @0,@1 |
121 | .endm |
122 | |
123 | .macro ldi16x ; @0 untere REG_Nr, @1 Data16 2-4 c |
124 | ; wenn REG 0...14, r16 benutzt |
125 | ldi8_x @0,low(@1) |
126 | ldi8_x @0+1,high(@1) |
127 | .endm |
128 | |
129 | .macro ldi24x ; @0 untere REG_Nr, @1 Data24 3-6 c |
130 | ; wenn REG 0...13, r16 benutzt |
131 | ldi8_x @0,low(@1) |
132 | ldi8_x @0+1,high(@1) |
133 | ldi8_x @0+2,byte3(@1) |
134 | .endm |
135 | |
136 | .macro ldi32x ; @0 untere REG_Nr, @1 Data32 4-8c |
137 | ; wenn REG 0...12, r16 benutzt |
138 | ldi8_x @0,low(@1) |
139 | ldi8_x @0+1,high(@1) |
140 | ldi8_x @0+2,byte3(@1) |
141 | ldi8_x @0+3,byte4(@1) |
142 | .endm |
143 | |
144 | .macro ldi40x ; @0 untere REG_Nr, @1 Data40 5-10c |
145 | ; wenn REG 0...11, r16 benutzt |
146 | ldi32x @0,@1 |
147 | ldi8_x @0+4,(@1>>32)&0xff |
148 | .endm |
149 | |
150 | ldi32x REG5,0x01020304 |
Maxim B. schrieb: > Ich habe Gefühl, man kann besser machen. Aber wie? Fachbücher lesen? Einen guten Kurs besuchen? Grundlagen erlernen (im Selbststudium) - so etwas ähnliches mit "Schwarmintelligenz" machst Du ja, aber ob Dir das wirklich etwas bringt? Google scheint nicht unbedingt Dein Freund zu sein, scheint mir. Schau doch mal ein wenig rum - z. B.: https://www.schramm-software.de/tipps/makros.htm Einfach mal "avr assembler makro" bei Google eingeben und rumstöbern kannst Du nicht?
Maxim B. schrieb: > Ich habe Gefühl, man kann besser machen. Aber wie? Versuch es mit C, BASIC, irgendwas - alles ist besser als das, was du als macro gepostet hast...
Marc V. schrieb: > Versuch es mit C, BASIC, irgendwas - alles ist besser als das, was du > als macro gepostet hast... Na, Assembler-Polizei gibt es in Deutschland noch nicht. Man darf alles :) Hugo H. schrieb: > Google scheint nicht unbedingt Dein Freund zu sein Das stimmt. Wenn ich Google etwas frage, dann bekomme ich ausschließlich Angebote etwas zu kaufen. Mehr kann Google leider nicht. Alles, was ich in Internet bisher fand, beschreibt Anfang. Bis Macro-Syntax kommt kaum ein Buch, leider. Wäre mein Lebenstraum mit LED zu blinken, dann wäre Google richtige Adresse für mich.
:
Bearbeitet durch User
Maxim B. schrieb: > Das stimmt. Wenn ich Google etwas frage, dann bekomme ich ausschließlich > Angebote etwas zu kaufen. Dann stellst Du die falschen Fragen. Hast Du mal meinen "Vorschlag" ausprobiert?
Marc V. schrieb: > Versuch es mit C Meinst du das? Ja, ich habe das ausprobiert. C bleibt sowieso. Aber ich möchte gerne auch etwas mit Assembler machen.
:
Bearbeitet durch User
Hugo H. schrieb: > https://www.schramm-software.de/tipps/makros.htm Danke für Link. Ich lese gerade. Hugo H. schrieb: > Dann stellst Du die falschen Fragen. Aus Pädagogik ist bekannt: falsche Fragen gibt es nicht. Es gibt nur falsche Lehrer.
:
Bearbeitet durch User
Maxim B. schrieb: > Aus Pädagogik ist bekannt: falsche Fragen gibt es nicht. Es gibt nur > falsche Lehrer. Was hat die Pädagogik mit Google gemeinsam? Natürlich gibt es falsche Fragen. Wenn Du die Uhrzeit wissen willst und fragst "Wo ist nächste Tankstelle" ist das nicht gerade die richtige Frage, um Deine Wissenslücke zu schließen - oder?
Dein Link ist interessant. Leider wird nur Anfang beschrieben. Besonders weit mit Macros kommt Autor nicht, wie auch von ihm empfohlene Seite. Meine Frage wird dort leider nicht beantwortet (automatische Unterschied zwischen oberen und unteren Register und auch indirekte Registerzugriff). c-hater konnte mir hier mehr helfen.
:
Bearbeitet durch User
Natürlich hat Google mit Pädagogik wenig zu tun. Google will nur alles verkaufen und mit Werbung verdienen. Nur durch Zufall kann von Google etwas Nützliche kommen.
Maxim B. schrieb: > Nur durch Zufall kann von Google > etwas Nützliche kommen. Im Falle dessen, der es nicht bedienen kann, stimme ich Dir voll und ganz zu.
:
Bearbeitet durch User
Beitrag #6663992 wurde vom Autor gelöscht.
Maxim B. schrieb: > C bleibt sowieso. Aber ich möchte gerne auch etwas mit Assembler machen. Kannst du auch in C ohne Probleme. Ein Macro wird in Assembler immer in voller Länge eingefügt, eine function mit entsprechenden Parametern in C aber nur einmal.
:
Bearbeitet durch User
Marc V. schrieb: > Ein Macro wird in Assembler immer in voller Länge eingefügt Das finde ich schön. Auch in C mag ich Macro und inline-Funktionen als volatile. Wenn ich Programmspeicher nicht vollständig benutze, bekomme ich kein Geld zurück. :) Jetzt habe ich noch etwas bemerkt: wenn ich so schreibe:
1 | .if (var > Konst) |
2 | *** |
3 | .endif |
, arbeitet das nicht mit 2147483647. D.h. int32_t, 0x7FFFFFFF. .if (var > 2147483647) wird immer war. Das liegt wohl in Assemblerprogramm. Kann man das nicht umgehen?
:
Bearbeitet durch User
Maxim B. schrieb: > int32_t https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ganzzahlige_Datentypen_.28Integer.29
Maxim B. schrieb: > Was wolltest du damit sagen? Ich dachte, Du kannst Lesen? Was sagt Dir der Datentyp int32_t? Das ist übrigens ein gutes Beispiel (aus meiner Sicht) für den Unterschied zwischen Assembler und Compiler (bzw. Interpreter). Der Assembler setzt das, was Du vorgegeben hast, 1:1 in Maschinencode um. Du hast (fast) immer Recht. Der Compiler versucht "zu ergründen" was Du willst und warnt Dich vor "unsinnigen" Befehlen. Ein Interpreter (wie Basic) macht das gleiche - nur immer wieder zum Laufzeitpunkt - mit entsprechender Performance-Einbuße.
:
Bearbeitet durch User
Marc V. schrieb: > Ein Macro wird in Assembler immer in voller Länge eingefügt, eine > function mit entsprechenden Parametern in C aber nur einmal. Nein. Du lügst. C macht natürlich inlining. Der Unterschied zu Asm ist: hier habe ich die volle Kontrolle, wofür genau. In C entscheidet das letztlich der Compiler. Und eben längst nicht immer richtig... Man kann ein wenig frickeln, um ihn in die richtige Richtung zu lenken, aber die volle Kontrolle erlangt man nicht.
Maxim B. schrieb: > Mein Wunsch wäre, daß in Macro Unterschied zwischen r0-r15 und r16-r31 > erkannt wird, so daß ich gewöhnliche Syntax mit Register verwenden > könnte. Wäre auch möglich, geht aber weiterhin in die falsche Richtung. Deswegen werde ich deine Bemühungen auch nicht weiter unterstützen, sondern empfehlen: nimm C. Du bist wohl nicht für Asm geboren, du bist schließlich offensichtlich nicht einmal in der Lage, die Möglichkeiten des (eines!) Assemblers beim Präprozessing zu erkennen und zu benutzen. Es ist also kaum anzunehmen, dass du dann zur Laufzeit Bäume in Asm ausreissen wirst. Denn dazu ist es nötig (für jede Zielarchitektur auf's Neue) zu erkennen, was man damit tuen kann und wie man das am effizientesten tut, also dieselbe Challenge wie beim Präprozessor für die Assemblierzeit. Es ist also mit extrem hoher Wahrscheinlichkeit davon auszugehen, dass dein Code deutlich schlechter werden wird, als hätte man ihn gleich in Schulbuch-C hingeschrieben und (mit Optimierung) kompiliert. Unter solchen Voraussetzungen ergibt der Einsatz von Asm eher keinen Sinn. Die Sache ist: ein Assembler produziert exakt den Code, den die Fähigkeiten seines Programmierers erlauben. Ein C-Compiler kann hingegen besseren Code liefern, als es die Programmiererfähigkeiten eigentlich erlauben würden... Deswegen wohl der verbreitete Eindruck, dass C schon alles richtet. Den haben vor allem diese Unmassen krass unfähiger C-only Programmierer...
Hugo H. schrieb: > Der Assembler setzt das, was Du vorgegeben hast, 1:1 in Maschinencode > um. Du hast (fast) immer Recht. Diese Frage betrifft aber Assembler nicht, nur Präprozessor. Hast du gelesen, was ich zuletz gefragt habe? Oder kannst du nur schreiben? c-hater schrieb: > sondern > empfehlen: nimm C. Ich werde beides verwenden.
:
Bearbeitet durch User
Beitrag #6665503 wurde von einem Moderator gelöscht.
Beitrag #6665574 wurde von einem Moderator gelöscht.
Beitrag #6665587 wurde von einem Moderator gelöscht.
Beitrag #6665596 wurde von einem Moderator gelöscht.
Beitrag #6665616 wurde von einem Moderator gelöscht.
Beitrag #6665629 wurde von einem Moderator gelöscht.
Beitrag #6665633 wurde von einem Moderator gelöscht.
Beitrag #6665784 wurde von einem Moderator gelöscht.
c-hater schrieb: > Du bist wohl nicht für Asm geboren Ja, ich weiß. Ich bin für Bachsche Orgelmusik geboren. Und auch für Orgelmusik von Buxtehude. Elektronik ist nur Hobby für mich. Ist das schlecht? c-hater schrieb: > Es ist also mit extrem hoher Wahrscheinlichkeit davon auszugehen, dass > dein Code deutlich schlechter werden wird, als hätte man ihn gleich in > Schulbuch-C hingeschrieben und (mit Optimierung) kompiliert. Mag sein. Aber diese Spielerei mit Macro kann behilflich werden, wenn ich einen Algorithmus aus C auf Assembler verwenden möchte, ohne zu viel darüber zu denken (als Beispiel: Universelle Tastenabfrage, was ich gerne mehrmals in meine C-Proekte übernommen habe: Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung" Eine Erweiterung auf 16 oder auf 24 Tasten wird in C natürlich viel einfacher. Aber wenn alles Andere mit Assembler gemacht wird? ). Wozu kann das behilflich sein? Ganz einfach: wenn das Programm auf Assembler geschrieben wird, aber eine oder zwei Funktionen relativ kompliziert sind und ich habe kein Vorbild auf Assembler gefunden. Mit Assembler gehen die Sachen besser, die viel mit Peripherie zu tun haben und wo wenig von den Sachen ist, wofür C konzipiert ist (Peripherie macht sowieso Quelltext-Übertragen auf andere Systeme fragwürdig). Z.B. wenn man, wie hier auf dem Forum irgendwo gepostet wurde, einen Ersatz für LM3914 machen will, paßt Assembler besser als C: ADC auslesen und entsprechend bestimmte Ausgänge umschalten. Vergleich mit Konstante und bedingte cbi und sbi. c-hater schrieb: > Ein C-Compiler kann hingegen > besseren Code liefern, als es die Programmiererfähigkeiten eigentlich > erlauben würden... Gerade für Anfänger bedeutet C viel Kampf mit "Wegoptimieren" :) Assembler macht genau was geschrieben. Um zu verstehen, welche Vorteil das bringt, lohnte es sich, C kennenzulernen...
:
Bearbeitet durch User
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.