mikrocontroller.net

Forum: Compiler & IDEs Inline assembler Anfänger


Autor: Udo Scharnitzki (Firma: allround) (1udo1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benötige eine Anfahrhilfe für den Inline assembler. Ihr kennt 
sicherlich dieses Beispiel aus dem Tutorial:

Meine Frage:

Der Aufruf des Assmblers soll doch die Bits 0000 0101 im Register 
"result" um ein Bit nach rechts verschieben.
Danach soll der neue Wert, also 0000 1010 in value abgespeichert sein, 
oder?
Im AVR Studio wird in 60H die 05H und in 62H die 04H angezeigt.

Ich mache sicherlich einen fehler, weiß aber nicht wo. Kann jemand mir 
sagen, wo es lang geht?


Udo


#include <avr/io.h>

  int  result=5;
  int  value=4;
  int  TAPP;

void main(void)
{
  DDRB =0xff;
  while (1)
  {
  asm("mov %0, %1, ror#1" : "=r" (result) : "r" (value));
  PORTB=TAPP;
  TAPP++;
  }
}

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du tatsächlich von
>> 0b0000 0101
nach
>> 0b0000 1010
schieben willst - geht das mit ROL ('L' wie links) besser ;)
 //und
asm("mov %0, %1 ror#1" : "=r" (result) : "r" (value));
//wirst du wohl so (oder so aehnlich) schreiben muessen:
asm(    "mov %0, %1 \n\t"
        "ror %0     \n\t"
        : "=&r" (result)
        : "r" (value)  );
Lies dir unbedingt mal das 
http://www.roboternetz.de/wissen/index.php/Inline-... 
durch.

hth. Jörg

Autor: Udo Scharnitzki (Firma: allround) (1udo1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

Danke für Deine Antwort. Leider funktioniert Dein Vorschlag auch nicht. 
Die Zellen bleiben unverändert mit den Anfangswerten. Der Inline 
assembler bewirkt nichts.

Ich verstehe das nicht. Dieses Beispiel ist doch wirklich nicht 
kompliziert. Der Compiler meldet keinen Fehler und ber built ist auch 
o.k.
Das Manual, dass Du mir empfohlen hast, habe ich schon von vorne bis 
hinten und zurück gelesen. Auch andere Tutorials durchforstet. Es gibt 
mir keine weiteren Ideen, wie der Inline assembler meine Bits schieben 
kann. Funktionieret auf Deinem Rechner die Schieberei?

Habe die aktuellen Versionen von AVR Studio und gcc.


#include <avr/io.h>

  int  result=6;
  int  value=34;
  int  TAPP;

void main(void)
{
  DDRB =0xff;
  while (1)
  {
  asm("mov %0, %1, \n\t"   /* schiebt nicht!!*/
        "rol %0     \n\t"
        : "=&r" (result)
        : "r" (value)  );

    PORTB=TAPP;
    TAPP++;
  }
}

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht beschreibst du ja dein gesamtes Problem mal?  Der Inline-
Assembler ist eine riesige Kanone, mit der man besser nicht auf
Spatzen schießt.  Er benutzt viele der internen Compiler-Mechanismen
selbst, was ihn einerseits flexibel aber andererseits reichlich
unübersichtlich gestaltet.

Autor: Udo Scharnitzki (Firma: allround) (1udo1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

in meinem Bühnenprogramm setze ich viele verschiedenen LED Lauflichter 
mit 100en LEDs ein. Ebenfalls über Triacs gesteuerte Lichtanlagen. Viele 
Lichtmuster erzeuge ich mit Rotationen im Akku. In gcc gibt es meines 
Erachtens keinen vergleichbaren Rotationsbefehl, oder doch? Diese 
Rotation im Akku brauche ich immer wieder. Aber natürlich genauso die 
kurzen Ausgabebefehle, Warteschleifen usw. mit gcc.

Kurzum:

Ich möchte meine Programme mit gcc in Verbindung mit dem Inline 
assembler optimieren. Das ist der Grund, warum ich den Inline assembler 
nutzen möchte.

Mich würde mal wirklich interessieren, ob ich einer der Wenigen bin, bei 
denen die Beispiele aus dem AVR Tutorial, Roboternetz Wissen usw. nicht 
klappen.

Muss der Inline assembler im C-Programm vielleicht vorher irgendwie 
angekündigt werden. Wenn es bei mir nicht klappt, dann dürfte es doch 
bei allen, die AVR Sudio4 und gcc benutzen (aktuellste Version) auch 
nicht klappen.

Noch zum Schluß:

Habe folgendes noch probiert:

void main(void)
{
  DDRB =0xff;
  DDRD =0xff;
  while (1)
  {

   PORTD=TAPP;
   TAPP--;

   asm("mov %0, %1, \n\t"
   "rol %0     \n\t"
   : "=&r" (result)
   : "r" (value)  );

  PORTB=TAPP;
  TAPP++;
  }
}

Im AVR Studio Simulator springt beim Single Step der Cursor immer nur 
von Ausgabe PORTD zu Ausgabe PORTB. Der Inline assembler kommt gar nicht 
zum Zug. Also auch keine Rotation.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ICH hatte das auch gestern abend nicht getestet.
So funktioniert dein Beispiel - auch wenn ich nicht exakt weiß, was es 
tun soll ;) - d.h. es compiliert und simuliert.
#include <stdint.h>
#include <avr/io.h>"

int main(void)
{

  uint8_t result = 0x01;
  int8_t step = 0x74;
  DDRB =0xff;
  DDRD =0xff;
  while (1){

     PORTD = step;
     step--;

     asm ("mov %0, %1 \n\t"
    "rol %0     \n\t"
    : "=&r" (result)
    : "r" (step)  );

    PORTB = result;
    
  }
}
Aber auch ich hab was gelernt - ich werde den Inline Assembler solange 
meiden wie die Hölle, solange irgednwie möglich.
 Es scheint ja definitiv leichter aus einem .lss- oder .s-File ein neues 
.S-File zu machen, als jedes mal wieder die Inline-Assembler-doku zu 
bemühen ;)

hth. Jörg
ps.:
> Ich möchte meine Programme mit gcc in Verbindung mit dem Inline
> assembler optimieren.
ein heres Ziel, ist aber mit einem C-Buch und der (besser 
verständlichen) AVR-libc-doku einfacher zu erreichen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, ROL und ROR rotieren ja nicht wirklich das Register, sondern
sie rotieren aus dem / in das Carry-Flag.  Um das Register zu rotieren,
brauchst du also noch ein paar Assemblerbefehle mehr.  Letztlich bist
du dann ebenso bei 4 Befehlen, wie die C-Notation.

Hier mein Testbeispiel:
#include <inttypes.h>
#include <avr/io.h>

static inline uint8_t
rol(uint8_t x)
{
#ifdef USE_ASM
        asm volatile(
                "clc" "\n\t"
                "sbrc %0, 7" "\n\t"
                "sec" "\n\t"
                "rol %0"
                : "=&r"(x));
        return x;
#else
        uint8_t y;

        y = x << 1;
        if (x & 0x80) y |= 1;

        return y;
#endif
}

void
flicker(uint8_t x)
{

        PORTB = x;
        x = rol(x);
        PORTB = x;
        x = rol(x);
        PORTB = x;
}

Es finden sich im Code ein paar überflüssige "clr r25", aber das ist
unabhängig davon, ob man mit -DUSE_ASM oder nicht compiliert.
Letztlich spart die inline-assembler-Version für die Funktion
flicker() ganze zwei Takte ein (14 statt 16).  Weiß nicht, ob das
wirklich den Aufwand mit der Kryptizität des inline asm Wert ist.

Autor: Udo Scharnitzki (Firma: allround) (1udo1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, Jörg,


Danke für Deine Mühe,

das geht mir zu sehr ins Eingemachte. Ich kann das mit meinen bisherigen 
Kenntnissen nicht nachvollziehen, was da im compiler passiert. Also, 
werde ich den inline assembler zu den Akten legen.

Eine abschließende Frage:

Gibt es überhaupt eine sinnvolle Alternative in gcc den 
Rotationsbefehl,-- wie im assembler --- umzusetzen? Oder geht das im gcc 
nur über Umwege, die allein der wirklich versierte Experte (effizient?) 
programmieren kann.

Udo

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schrieb doch oben schon, Rotieren in deinem Sinne kann selbst
der Assembler nicht.  ROL und ROR sind Schiebebefehle, keine echten
Rotationen.

Der Compiler benutzt ROL/ROR und SHL/SHR bereits.

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.