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++; } }
Wenn du tatsächlich von >> 0b0000 0101 nach >> 0b0000 1010 schieben willst - geht das mit ROL ('L' wie links) besser ;)
1 | //und
|
2 | asm("mov %0, %1 ror#1" : "=r" (result) : "r" (value)); |
3 | //wirst du wohl so (oder so aehnlich) schreiben muessen:
|
4 | asm( "mov %0, %1 \n\t" |
5 | "ror %0 \n\t" |
6 | : "=&r" (result) |
7 | : "r" (value) ); |
Lies dir unbedingt mal das http://www.roboternetz.de/wissen/index.php/Inline-Assembler_in_avr-gcc durch. hth. Jörg
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++; } }
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.
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.
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.
1 | #include <stdint.h> |
2 | #include <avr/io.h>" |
3 | |
4 | int main(void) |
5 | {
|
6 | |
7 | uint8_t result = 0x01; |
8 | int8_t step = 0x74; |
9 | DDRB =0xff; |
10 | DDRD =0xff; |
11 | while (1){ |
12 | |
13 | PORTD = step; |
14 | step--; |
15 | |
16 | asm ("mov %0, %1 \n\t" |
17 | "rol %0 \n\t" |
18 | : "=&r" (result) |
19 | : "r" (step) ); |
20 | |
21 | PORTB = result; |
22 | |
23 | }
|
24 | }
|
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.
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:
1 | #include <inttypes.h> |
2 | #include <avr/io.h> |
3 | |
4 | static inline uint8_t |
5 | rol(uint8_t x) |
6 | {
|
7 | #ifdef USE_ASM
|
8 | asm volatile( |
9 | "clc" "\n\t" |
10 | "sbrc %0, 7" "\n\t" |
11 | "sec" "\n\t" |
12 | "rol %0"
|
13 | : "=&r"(x)); |
14 | return x; |
15 | #else
|
16 | uint8_t y; |
17 | |
18 | y = x << 1; |
19 | if (x & 0x80) y |= 1; |
20 | |
21 | return y; |
22 | #endif
|
23 | }
|
24 | |
25 | void
|
26 | flicker(uint8_t x) |
27 | {
|
28 | |
29 | PORTB = x; |
30 | x = rol(x); |
31 | PORTB = x; |
32 | x = rol(x); |
33 | PORTB = x; |
34 | }
|
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.
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
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.
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.