2016-10-29 1 views
0

I diesen Code habe:AVR GCC, Montag C Stub-Funktionen, und der erforderliche EOR konstante Wert

uint16_t swap_bytes(uint16_t x) 
{ 
    asm volatile(
     "eor, %A0, %B0"  "\n\t" 
     "eor, %B0, %A0"  "\n\t" 
     "eor, %A0, %B0"  "\n\t" 
     : "=r" (x) 
     : "0" (x) 
    ); 
    return x; 
} 

die (durch AVR- gcc version 4.8.1 mit -std=gnu99 -save-temps) zu übersetzt:

.global swap_bytes 
    .type swap_bytes, @function 
swap_bytes: 
/* prologue: function */ 
/* frame size = 0 */ 
/* stack size = 0 */ 
.L__stack_usage = 0 
/* #APP */ 
; 43 "..\lib\own\ownlib.c" 1 
    eor, r24, r25 
    eor, r25, r24 
    eor, r24, r25 

; 0 "" 2 
/* #NOAPP */ 
    ret 
    .size swap_bytes, .-swap_bytes 

Aber dann beschwert sich der Compiler so:

|65|Error: constant value required| 
|65|Error: garbage at end of line| 
|66|Error: constant value required| 
|66|Error: garbage at end of line| 
|67|Error: constant value required| 
|67|Error: garbage at end of line| 
||=== Build failed: 6 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 

Die erwähnten Zeilen sind diejenigen mit den eor Befehlen. Warum hat der Compiler damit Probleme? Die Register sind sogar obere (> = r16), wo fast alle Operationen möglich sind. constant value required klingt für mich wie es ein wörtliches erwartet ... Ich verstehe es nicht.

+0

gcc hat dafür eingebaut. Warum nicht diese benutzen? Sie sind sowieso compilerabhängig. Warum nicht einfach C verwenden? – Olaf

+0

Ich bin mit Olaf: Verwenden Sie eingebaute, wenn Sie können. Wenn Sie jedoch inline asm verwenden müssen, frage ich mich, ob Ihr Problem ein "extra" -Komma ist. Googlen für avr eor erscheint 'eor r4, r4' und' eor r0, r22' (no no comma nach dem Befehl eor). Ich bin kein Avr-Experte, aber das würde ich zuerst versuchen. –

+0

f # * k! Du hast recht. da sollte kein '' '' sein. Jedenfalls sind AVRs Mikrocontroller, daher ist der Programmplatz eng. 3 Anleitung ist unschlagbar für C. Danke nochmal! – milkpirate

Antwort

0

Gerade für zukünftige Googler zu klären:

eor, r24, r25 

hat ein zusätzliches Komma nach dem EOR. Dies sollte wie folgt geschrieben werden:

eor r24, r25 

Ich würde Sie auch ermutigen, (wieder) zu prüfen, gcc mit __builtin_bswap16. Falls Sie mit den eingebauten Funktionen von gcc nicht vertraut sind, handelt es sich um Funktionen, die in den Compiler integriert sind und (obwohl sie wie Funktionen aussehen) typischerweise inline sind. Sie wurden von Leuten geschrieben und optimiert, die alle Einzelheiten der verschiedenen Prozessoren verstehen und Dinge berücksichtigen können, die Sie vielleicht nicht berücksichtigt haben.

Ich verstehe den Wunsch, den Code so klein wie möglich zu halten. Und ich akzeptiere, dass es möglich ist, dass (irgendwie) das, das auf Ihrem spezifischen Prozessor eingebaut wird, suboptimalen Code produziert (ich nehme an, dass Sie überprüft haben?). Auf der anderen Seite kann es genau den gleichen Code produzieren. Oder es könnte einen noch schlaueren Trick dazu verwenden. Oder es könnte Anweisungen aus dem umgebenden Code verschachteln, um Pipelining zu nutzen (oder eine andere avr-spezifische Sache, von der ich noch nie gehört habe, weil ich nicht 'avr' spreche).

Was mehr ist, sollten Sie diesen Code:

int main() 
{ 
    return __builtin_bswap16(12345); 
} 

Ihr Code nimmt immer 3 Anweisungen, um einen Swap zu verarbeiten. Mit Builtins kann der Compiler jedoch erkennen, dass der Arg-Wert konstant ist, und den Wert zur Kompilierzeit statt zur Laufzeit berechnen. Schwer, effizienter zu sein.

Ich könnte auch die Vorteile von "einfacher zu unterstützen." Inline Asm schreiben ist schwer zu tun. Und zukünftige Betreuer hassen es zu berühren, weil sie sich nie ganz sicher sind, wie es funktioniert. Und natürlich wird das Built-in mehr plattformübergreifend portabel sein.

Immer noch nicht überzeugt? Meine letzte Tonhöhe: Selbst nachdem Sie die Kommas korrigiert haben, ist Ihr Inline-Asm-Code immer noch nicht ganz richtig. Betrachten Sie diesen Code:

int main(int argc, char *argv[]) 
{ 
    return swap_bytes(argc) + swap_bytes(argc); 
} 

Aufgrund der Art, die Sie geschrieben swap_bytes geschrieben haben (dh mit volatile), gcc müssen den Wert berechnen zweimal (siehe die Definition von volatile). Hätten Sie volatile ausgelassen (oder wenn Sie die eingebaute Funktion verwendet hätten, die dies richtig macht), hätte es erkannt, dass argc die Ausgabe des ersten Aufrufs nicht ändert und wiederverwendet. Habe ich erwähnt, dass das korrekte Schreiben von Inline-Asm HARD ist?

Ich kenne Ihren Code, Einschränkungen, Kenntnisstand oder Anforderungen nicht. Vielleicht ist deine Lösung wirklich die Beste. Das Meiste, was ich tun kann, ist, Sie zu ermutigen, lange und gründlich zu denken, bevor Sie in Produktionscode Inline-Asm verwenden.

Verwandte Themen