Forum: Mikrocontroller und Digitale Elektronik Warum kennt der Compiler das nicht (.set, .macro)


von Oz z. (ozzy)


Lesenswert?

Moin,

ich habe hier im Forum Code für schnelles Wurzelziehen in asm gefunden, 
und wollte den nun auch benutzen und einbinden. Also die .S-Datei 
runtergeladen, mit in mein Verzeichnis und bei AVR-Studio dem Projekt 
hinzugefügt. Dann kam aber schon die Fehler beim Kompilieren, z.B.

../sqrt.S:5: Error: expected comma after "useMOVW"
../sqrt.S:8: Error: expected comma after "useSpeedOptimized"
../sqrt.S:10: Error: expected comma after "saveRegs"
../sqrt.S:40: Error: unexpected end of file in macro `wurzel_shiftleft' 
definition

Hier der Code aus der Datei:
1
.set useMOVW = 1
2
.set useSpeedOptimized = 1
3
.set saveRegs = 0
4
5
.macro WURZEL_SHIFTLEFT
6
  //@0 @1 @2 @3 << 1
7
  lsl @3
8
  rol @2
9
  rol @1
10
  rol @0
11
.endmacro

Warum mag der Compiler denn so etwas nicht? In der Makefile steht die 
Datei richtig drin. Muss man denn noch irgendwo etwas konfigurieren / 
hinzufügen?

Vielen Dank für Eure Hilfe, MfG, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Syntax eines anderen Assemblers.  Du willst den GNU-Assembler benutzen,
der Code dürfte für den Atmel-AVR-Assembler geschrieben worden sein.

Probier mal:
1
.set useMOVW, 1
2
.set useSpeedOptimized, 1
3
.set saveRegs, 0
4
5
.macro WURZEL_SHIFTLEFT, a0, a1, a2
6
  //a0 a1 a2 a3 << 1
7
  lsl \a3
8
  rol \a2
9
  rol \a1
10
  rol \a0
11
.endm

Statt .set kann man im GNU-Assembler auch #define benutzen, da die
.S-Dateien vom Compiler zuvor noch durch den Präprozessor geschickt
werden.  Damit besitzt man eine zusätzliche Makro-Ebene oberhalb
des Assemblers.

von Oz z. (ozzy)


Lesenswert?

Moin,

habe es jetzt so umgeändert:
1
.MACRO WURZEL_SHIFTLEFT
2
  //@0 @1 @2 @3 << 1
3
  lsl @3
4
  rol @2
5
  rol @1
6
  rol @0
7
.ENDM
Jetzt gibt es da keine Fehlermeldungen mehr. Dafür aber bei z.B. diesem 
Aufruf:
1
WURZEL32_OUTERLOOP 15, (0x8000 >> 0)
der das Makro:
1
.MACRO WURZEL32_OUTERLOOP
2
    .if @0 == 0
3
      clr r19
4
      clr r18
5
      movw r17:r16, YH:YL
6
      WURZEL_SHIFTLEFT r19, r18, r17, r16
7
      ori r16, 1
8
    .elif @0 == 1
9
      WURZEL_lshift0 (@1>>1)
10
      WURZEL_SHIFTLEFT r19, r18, r17, r16
11
      WURZEL_SHIFTLEFT r19, r18, r17, r16
12
    .elif @0 == 2
13
      WURZEL_lshift0 (@1>>1)
14
      WURZEL_SHIFTLEFT r19, r18, r17, r16
15
      WURZEL_SHIFTLEFT r19, r18, r17, r16
16
      WURZEL_SHIFTLEFT r19, r18, r17, r16
17
    .elif @0 == 3
18
      WURZEL_lshift0 (@1>>1)
19
      WURZEL_SHIFTLEFT r19, r18, r17, r16
20
      WURZEL_SHIFTLEFT r19, r18, r17, r16
21
      WURZEL_SHIFTLEFT r19, r18, r17, r16
22
      WURZEL_SHIFTLEFT r19, r18, r17, r16
23
    .elif @0 == 4
24
      WURZEL_lshift8 (@1>>1)
25
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
26
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
27
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
28
    .elif @0 == 5
29
      WURZEL_lshift8 (@1>>1)
30
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
31
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
32
    .elif @0 == 6
33
      WURZEL_lshift8 (@1>>1)
34
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
35
    .elif @0 == 7
36
      WURZEL_lshift8 (@1>>1)
37
    .elif @0 == 8
38
      WURZEL_lshift8 (@1>>1)
39
      WURZEL_SHIFTLEFT r19, r18, r17, r16
40
    .elif @0 == 9
41
      WURZEL_lshift8 (@1>>1)
42
      WURZEL_SHIFTLEFT r19, r18, r17, r16
43
      WURZEL_SHIFTLEFT r19, r18, r17, r16
44
    .elif @0 == 10
45
      WURZEL_lshift8 (@1>>1)
46
      WURZEL_SHIFTLEFT r19, r18, r17, r16
47
      WURZEL_SHIFTLEFT r19, r18, r17, r16
48
      WURZEL_SHIFTLEFT r19, r18, r17, r16
49
    .elif @0 == 11
50
      /*WURZEL_lshift8 (@1>>1)
51
      WURZEL_SHIFTLEFT r19, r18, r17, r16
52
      WURZEL_SHIFTLEFT r19, r18, r17, r16
53
      WURZEL_SHIFTLEFT r19, r18, r17, r16
54
      WURZEL_SHIFTLEFT r19, r18, r17, r16*/
55
      WURZEL_lshift16 (@1>>1)
56
      WURZEL_RORRIGHT r19, r18, r17, r16
57
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
58
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
59
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
60
    .elif @0 == 12
61
      WURZEL_lshift16 (@1>>1)
62
      WURZEL_RORRIGHT r19, r18, r17, r16
63
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
64
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
65
    .elif @0 == 13
66
      WURZEL_lshift16 (@1>>1)
67
      WURZEL_RORRIGHT r19, r18, r17, r16
68
      WURZEL_SHIFTRIGHT r19, r18, r17, r16
69
    .elif @0 == 14
70
      WURZEL_lshift16 (@1>>1)
71
      WURZEL_RORRIGHT r19, r18, r17, r16
72
    .elif @0 == 15
73
      WURZEL_lshift16 (@1>>1)
74
    .else
75
      .error "ooops!!!"
76
    .endif
77
    cp r2, r16
78
    cpc r3, r17
79
    cpc r4, r18
80
    cpc r5, r19
81
    brlo wurzel32_2f_wd
82
      subi YL,  LOW(~@1+1)
83
      sbci YH, HIGH(~@1+1)
84
      sub r2, r16
85
      sbc r3, r17
86
      sbc r4, r18
87
      sbc r5, r19
88
  wurzel32_2f_wd:
89
  
90
.ENDM
und zwar die Fehlermeldung:
../sqrt.S:272: Error: too many positional arguments

Der Thread zu der Wurzelfunktion ist übrigens hier:
Beitrag "[ASM] (schnelle) Integer Wurzel 32bit"

Vielen Dank für Eure Hilfe, MfG, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Warum zum Geier[tm] änderst du es nicht so, wie ich es dir nahe gelegt
habe?

Wenn du mich ignorierst und ohnehin erst alles (offenbar ohne Benutzung
des Manuals) trial&error selbst machen willst, dann brauch' ich dir
ja auch nicht mehr zu schreiben...

von Oz z. (ozzy)


Lesenswert?

Hi,

ich habe es mittlerweile ja schon geändert (hatte Deinen Post vorher 
nicht gesehen).
Aber das ändert nicht viel, nur haben sich die Fehlermeldungen 
verändert:
../sqrt.S:165: Error: garbage at end of line

Das Makro mit passendem Aufruf funktioniert jetzt:
1
.MACRO WURZEL_SHIFTLEFT a3,a2,a1,a0
2
  //\a0 \a1 \a2 \a3 << 1
3
  lsl \a3
4
  rol \a2
5
  rol \a1
6
  rol \a0
7
.ENDM
8
9
WURZEL_SHIFTLEFT r16, r17, r18, r19

Nur noch bei der Fkt oben gibt es Probleme. Ich habe beim Makro die 
parameter mitgegeben:
1
.MACRO WURZEL32_OUTERLOOP a0, a1
und die @0 durch \a0, und die @1 durch \a1 geändert.
Jetzt bekomme ich zuerst ein "ooops!!!", da er wohl den ersten Parameter 
nicht erkennt.

Hast Du da noch eine Idee??

MfG und vielen Dank, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph O. wrote:

> ../sqrt.S:165: Error: garbage at end of line

Und welche Zeile ist das?

> Jetzt bekomme ich zuerst ein "ooops!!!", da er wohl den ersten Parameter
> nicht erkennt.

Ich denke nicht, dass man mit dem Parameterwert eines Makros eine
bedingte Assemblierung vornehmen lassen kann.  Wenn ich das hier:
1
.macro a a0 r
2
.if a0 == 1
3
        ldi     r\r, 1
4
.elif a0 == 2
5
        ldi     r\r, 2
6
.else
7
        ldi     r\r, 42
8
.endif
9
.endm
10
11
a 1 16
12
a 2 17
13
a 3 18

assemblieren lasse und wieder disassembliere, erhalte ich:
1
foo.o:     file format elf32-avr
2
3
Disassembly of section .text:
4
5
00000000 <.text>:
6
   0:   0a e2           ldi     r16, 0x2A       ; 42
7
   2:   1a e2           ldi     r17, 0x2A       ; 42
8
   4:   2a e2           ldi     r18, 0x2A       ; 42

Also auch nur jeweils die letzte Verzweigung.

von Oz z. (ozzy)


Lesenswert?

Hi,

also ich konnte den Fehler jetzt auf folgende Zeile(n) begrenzen:
1
subi YL,  LOW(~\a1+1)
, was ich von folgender Zeile geändert hatte:
1
subi YL,  LOW(~@1+1)

Noch eine Idee, wie man das in den Griff bekommt?

MfG, und vielen Dank für Deine Hilfe, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hast du denn irgendwo einen Makro namens LOW definiert?

Die Operatoren im avr-as heißen lo8() und hi8().

von Oz z. (ozzy)


Lesenswert?

Hi,

nein, habe ich nicht. Aber ich habe früher einiges in Assembler 
programmiert, und da z.B. auch Befehle wie
1
zeichenkette:    .db    "Set:[HH][MM][SS]";,NUL
2
3
ldi    ZL, LOW(zeichenkette<<1)
4
ldi    ZH, HIGH(zeichenkette<<1)
gehabt, und die Programme funktionierten immer. Programmiert hatte ich 
damals auch in AVR Studio auf dem ATmega32, dann allerdings eben keine 
C, sondern reine Assembler-Programme, daher auch meine jetzigen 
Probleme...

Aber vielen Dank für Deine Hilfe, die Fehler sind jetzt weg. Mit dem 
if/elif muss ich noch mal schauen, ich wundere mich nur, dass es bei dem 
Thread-Ersteller geklappt hat...

MfG, und vielen Dank noch einmal, Ozzy

von Oz z. (ozzy)


Lesenswert?

Noch eine kleine Frage: "BYTE" kennt er wohl auch nicht:
1
subi r17, BYTE1(~\a0+1)
2
sbci r18, BYTE2(~\a0+1)
3
sbci r19, BYTE3(~\a0+1)
Durch was ersetzt man das denn bei avr-as.

Und noch ganz wichtig: Kannst Du mir eine Quelle nennen, wo man so etwas 
auch nachlesen kann?

MfG, und wirklich vielen, vielen Dank, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph O. wrote:

> Aber vielen Dank für Deine Hilfe, die Fehler sind jetzt weg. Mit dem
> if/elif muss ich noch mal schauen, ich wundere mich nur, dass es bei dem
> Thread-Ersteller geklappt hat...

Offenbar verhält sich der Atmel-AVR-Assembler da einfach mal anders
als der GNU-Assembler.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph O. wrote:

> Durch was ersetzt man das denn bei avr-as.

Ich kann nur raten, was diese Operatoren beim Atmel-Assembler machen.
Demnach wären sie wohl äquivalent zu hi8(), hlo8() und hhi8().

Allerdings frage ich mich gerade, wie man den gas dazu überredet, den
Ausdruck nicht als vom Typ int, sondern als long int zu berechnen,
sodass die Benutzung von hlo8() und hhi8() überhaupt Sinn hat.

> Und noch ganz wichtig: Kannst Du mir eine Quelle nennen, wo man so etwas
> auch nachlesen kann?

Der GNU-Assembler kommt mit sogenannten info-Dateien daher, da sind die
Pseudo-Ops (einschließlich Makros etc.) erklärt.  Bei mir tippe ich
dafür einfach "info as" ein.  Ich glaube, WinAVR bringt die zugehörige
Doku auch irgendwo mit.

Die AVR-spezifischen Pseudo-Ops sind außerdem hier erklärt:

http://www.nongnu.org/avr-libc/user-manual/assembler.html#ass_pseudoops

Leider fehlt dort noch die Erklärung für hlo8() und hhi8(), die erst
später dazu gekommen sind.

von Oz z. (ozzy)


Lesenswert?

Hi Jörg,

vielen Dank für Deine ganze Hilfe, jetzt kompiliert er wenigstens 
fehlerfrei, mal sehen, was er daraus so macht...

Übrigens funktioniert das mit der bedingten Assemblierung doch:
1
.macro a a0 r
2
.if \a0 == 1
3
        ldi     r\r, 1
4
.elseif \a0 == 2
5
        ldi     r\r, 2
6
.else
7
        ldi     r\r, 42
8
.endif
9
.endm
10
11
a 1 16
12
a 2 17
13
a 3 18
1
 27c:  01 e0         ldi  r16, 0x01  ; 1
2
 27e:  12 e0         ldi  r17, 0x02  ; 2
3
 280:  2a e2         ldi  r18, 0x2A  ; 42


Vielen Dank noch einmal, MfG, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph O. wrote:

> Übrigens funktioniert das mit der bedingten Assemblierung doch:

OK, pilot error.  Gut zu wissen, danke!

von Oz z. (ozzy)


Lesenswert?

Kein Problem. Das einzige, was leider noch nicht funktioniert: Der 
Sprung, da er immer sagt, dass er die Marke schon kennt. Klar, wenn er 
sie immer wieder einfügen möchte... Hast Du da eine Idee???
1
brlo wurzel32_2f_wd
2
  subi YL, lo8(~\a1+1)
3
  sbci YH, hi8(~\a1+1)
4
  sub r2, r16
5
  sbc r3, r17
6
  sbc r4, r18
7
  sbc r5, r19
8
wurzel32_2f_wd:

MfG, Ozzy

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph O. wrote:

> Kein Problem. Das einzige, was leider noch nicht funktioniert: Der
> Sprung, da er immer sagt, dass er die Marke schon kennt. Klar, wenn er
> sie immer wieder einfügen möchte... Hast Du da eine Idee???

Klar, local labels benutzen:
1
  brlo 1f
2
  subi YL, lo8(~\a1+1)
3
  sbci YH, hi8(~\a1+1)
4
  sub r2, r16
5
  sbc r3, r17
6
  sbc r4, r18
7
  sbc r5, r19
8
1:

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.