Forum: Mikrocontroller und Digitale Elektronik Eine Frage bzg. Macro in AVR-Assembler


von Maxim B. (max182)


Lesenswert?

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]

:
von Horst M. (horst)


Lesenswert?

Schau mal hier: Beitrag "AVR Assembler, Macro, Conditional mit Register"

Vielleicht kannst Du was draus übernehmen.

von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

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
von S. Landolt (Gast)


Lesenswert?

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.

von LostInMusic (Gast)


Lesenswert?

>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

von Maxim B. (max182)


Lesenswert?

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?

von Maxim B. (max182)


Lesenswert?

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
von c-hater (Gast)


Lesenswert?

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.

von Maxim B. (max182)


Lesenswert?

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

von S. Landolt (Gast)


Lesenswert?

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'

von c-hater (Gast)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

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

von Thomas R. (analogfreak)


Angehängte Dateien:

Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> 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

von c-hater (Gast)


Lesenswert?

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

von Rainer V. (a_zip)


Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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.

von Rainer V. (a_zip)


Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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

von Maxim B. (max182)


Lesenswert?

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
von Maxim B. (max182)


Lesenswert?

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
von S. Landolt (Gast)


Lesenswert?

> Danke!!! Das arbeitet!

Aha, interessant - und wie funktioniert nun das von Ihnen verlangte
> ldix32 r14,0xf1c2658a
d.h. das automatische Hochzählen von Registernummern?

von S. Landolt (Gast)


Lesenswert?

PS:
Denn ldix8 alleine hat schließlich auch in der von mir vorgeschlagenen 
Macro-Version funktioniert.

von Maxim B. (max182)


Lesenswert?

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

von Maxim B. (max182)


Lesenswert?

Ich habe Gefühl, man kann besser machen. Aber wie?

von Hugo H. (hugohurtig1)


Lesenswert?

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?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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

von Maxim B. (max182)


Lesenswert?

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
von Hugo H. (hugohurtig1)


Lesenswert?

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?

von Maxim B. (max182)


Lesenswert?

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
von Hugo H. (hugohurtig1)


Lesenswert?

Maxim B. schrieb:
> Meinst du das?

Lesen kannst Du aber schon - oder?

von Maxim B. (max182)


Lesenswert?

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
von Hugo H. (hugohurtig1)


Lesenswert?

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?

von Maxim B. (max182)


Lesenswert?

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
von Hugo H. (hugohurtig1)


Lesenswert?

Maxim B. schrieb:
> c-hater konnte mir hier mehr helfen.

Das freut mich - viel Spaß noch :-)

von Maxim B. (max182)


Lesenswert?

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.

von Hugo H. (hugohurtig1)


Lesenswert?

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.
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Maxim B. (max182)


Lesenswert?

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
von Hugo H. (hugohurtig1)


Lesenswert?


von Maxim B. (max182)


Lesenswert?

Was wolltest du damit sagen?

von Hugo H. (hugohurtig1)


Lesenswert?

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
von c-hater (Gast)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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

von Maxim B. (max182)


Lesenswert?

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.
von Maxim B. (max182)


Lesenswert?

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
Noch kein Account? Hier anmelden.