www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Multiplikation ATMega32


Autor: Daniel Günther (sirdaniel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe per InlineAssembler folgende kleine Routine zur Multiplikation 
zweier 8-Bit Zahlen geschrieben:

static inline res Multi_8x8_8(uint8_t a, uint8_t b)
{
  res r = {0, 0};

  asm volatile
  (
    "mul %2,%3 \n\t"          // a * b
    "mov %0,r0 \n\t"                      // r0 nach r.res0
    "mov %1,r1 \n\t"          // r1 nach r.res1
      :"=r" (r.res0), "=r" (r.res1)
      :"r" (a), "r" (b)
  );

  return r;
}

Sie tut auch ihren Dienst, solange bis das Produkt von a und b nicht 
größer als 255 also 8Bit ist. Kommt das Produkt über diesen Wert hinaus 
löst der Controller ständig einen Reset aus (die Funktion wird nur 
einmalig aus der main-Fkt. heraus aufgerufen, nicht im Mainloop!). res 
ist eine Struktur welche zwei uint8_t Integers beeinhaltet (also die 
beiden Ergebnis-Werte).

Vielen Dank für Eure Hilfe!

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du darfst r0 und r1 nicht so einfach verändern:

http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...

Autor: Daniel Günther (sirdaniel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso nicht? Ich habe mich dabei exakt an die AppNote 201 von Atmel 
gehalten; da wird der Inhalt von r0 und r1 nach der Multiplikation auch 
per movw woanders hingeschoben (movw hat bei mir nicht funktioniert, 
edshalb die Alternative mit 2 x mov)! Könntest du das bitte ein wenig 
genauer erläutern?

Vielen Dank!

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest mal das von Roland verlinkte Dokument lesen:

"r1 - assumed to be always zero in any C code, may be used to remember 
something for a while within one piece of assembler code, but must then 
be cleared after use (clr r1)."

Autor: Daniel Günther (sirdaniel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, Problem behoben! Musste nur r1 noch löschen nach der ganzen 
Prozedur! Das steht auch in dem was du mir geschickt hast, Roland! Danke 
dafür! Aber hast du eine Idee weshalb ihc den movw-Befehl nicht 
verwenden kann, der Compiler gibt mir immer die folgenden 
Fehlermeldungen:

Error: `,' required
Error: even register number required
Error: garbage at end of line

"movw %0:%1,r0:r1 \n\t"

Diese Zeile wird auch so assembliert wie ich mir das vorstelle wie es 
richtig sein müsste. Eine Idee?


MFG

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
movw kann nur auf das ungerade Register (oder warens gerade) angewendet 
werden. das neben an liegende wird dann ebenfalls mit ge'mov'ed

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...
steht eigentlich da:

> Error: even register number required

also müsste

movw %0, r0

funktionieren.

Autor: Daniel Günther (sirdaniel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal,

Nachdem die 8x8-Multiplikation wunderbar funktioniert habe ich mich 
jetzt mal an die 16x16 gewagt:

static inline res_32 Multi_16x16_32(uint16_t a, uint16_t b)
{
  res_32 r = {0, 0, 0, 0};

  asm volatile
  (
    "clr    r2        \n\t"
    "muls    HIGH(%4), HIGH(%5)    \n\t"
    "movw    r18, r0        \n\t"
    "mul    LOW(%4), LOW(%5)    \n\t"
    "movw    r16, r0        \n\t"
    "mulsu    HIGH(%4), LOW(%5)    \n\t"
    "sbc    r19, r2        \n\t"
    "add    r17, r0        \n\t"
    "adc    r18, r1        \n\t"
    "adc    r19, r2        \n\t"
    "mulsu    HIGH(%5), LOW(%4)    \n\t"
    "sbc    r19, r2        \n\t"
    "add    r17, r0        \n\t"
    "adc    r18, r1        \n\t"
    "adc    r19, r2        \n\t"
    "movw    %0, r16        \n\t"
    "movw    %2, r18        \n\t"
    "clr r1"

    :"=&r" (r.res0), "=&r" (r.res1), "=&r" (r.res2), "=&r"    (r.res3)
    :"d" (a), "d" (b)
  );

  return r;
}

Jetzt beschwert sich der Assembler in der Form

Error: constant value required
Error: register number above 15 required
Error: `,' required
Error: garbage at end of line

für jede Zeile in der HIGH() bzw. LOW() vorkommt. Was mache ich da 
falsch? Wie muss ich denn sonst getrennt auf High- bzw. Lowbyte 
zugreifen?

MFG

Daniel

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.