Aus RN-Wissen.de
Version vom 6. Juni 2006, 16:43 Uhr von SprinterSB_alt (Diskussion | Beiträge)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche
Rasenmaehroboter Test

Aus den unterschiedlichsten Gründen kann es wünschenswert sein, den Assembler-Code zu sehen, den gcc avr-gcc (oder gcc im Allgemeinen) aus einer C/C++-Quelle erzeugt. Die Ausgabe von gcc geschieht immer in Form von ASCII als Assembler-Datei. Ohne die Angabe spezieller Optionen ist diese Assembler-Datei jedoch nur temporär und wird nach Beenden der von gcc aufgerufenen Programme cc1, as und ld wieder gelöscht.

Ein Weg, den zu einer Quelle gehörenden Assembler-Code zu erhalten ist also, diese temporäre Datei zu erhalten, was mit der gcc-Option -save-temps geschieht, oder indem man nur assembliert, was mit der Option -S geschieht.

Alternativ dazu kann man durch objcopy ein Disassemble der erzeugten Objekte erzeugen.

Ja nach dem, welchen dieser Möglichkeiten man wählt, enthält die Assembler-Ausgabe unterschiedliche Informationen, Darstellungen und Erläuterungen.

Als C-Beispiel dient eine kleine Funktion, die einem Foren-Beitrag zu selbigem Thema entstammt. Die Assembler-Dumps sind jedoch nur Snips der kleinen Funktion foo, um die es hier gehen soll. Für komplexere Funktionen oder andere gcc-Targets (etwa arm7-gcc) ist die Vorgehensweise analog. Die main-Funktion wird nur gebraucht, damit für das letzte Beispiel ein elf erzeugt werden kann, da hier gegen main gelinkt wird.

C-Quelle

unsigned char command_rc5; 
unsigned char Ir_data_tmp; 

void foo()
{
   uint8_t cmd = command_rc5 & ~(1<<7);

   if (Ir_data_tmp & (1<<5))       
      cmd |= (1<<7);
   
   command_rc5 = cmd;   
} 

int main main()
{
	return 0;
}

Compiler dumpt Assembler

Kein Assemblieren

Die Arbeit von gcc endet mit Schreiben der Assembler-Ausgabe. Es wird also auch kein Object (*.o) erzeugt.

Kommando:

> avr-gcc -S -fverbose-asm ...

Ausgabe:

.global   foo
        .type   foo, @function
foo:
/* prologue: frame size=0 */
/* prologue end (size=0) */
        lds r25,command_rc5      ;  cmd, command_rc5
        andi r25,lo8(127)        ;  cmd,
        lds r24,Ir_data_tmp      ;  Ir_data_tmp, Ir_data_tmp
        sbrc r24,5       ;  Ir_data_tmp,
        ori r25,lo8(-128)        ;  cmd,
.L2:
        sts command_rc5,r25      ;  command_rc5, cmd
/* epilogue: frame size=0 */
        ret
/* epilogue end (size=1) */
/* function foo size 11 (10) */
        .size   foo, .-foo

mit Assemblieren

Wüschenswert wäre folgendes Kommando:

> avr-gcc -c -save-temps ...

Dies führt jedoch aus unerfindlichen Gründen zum Verlorengehen von Symbolen. Alternativ kann man zwei Aufrufe machen, was dummerweise etwas länger dauert und schwer in Makefile-Generatoren auszudrücken ist:

> avr-gcc -S -save-temps ...
> avr-gcc -c ...

Die Ausgabe ist dann wie im vorherigen Abschnitt, nur daß jetzt auch assembliert wird.

Assembler dumpt Assembler (kein Assemblieren)

Kommando:

> avr-gcc -c -Wa,-alhd=dump.s ...

Ausgabe:

  18                      .global foo
  20                    foo:
  21                    .LFB2:
  22                    .LM1:
  23                    /* prologue: frame size=0 */
  24                    /* prologue end (size=0) */
  25                    .LM2:
  26 0000 9091 0000             lds r25,command_rc5
  27 0004 9F77                  andi r25,lo8(127)
  28                    .LM3:
  29 0006 8091 0000             lds r24,Ir_data_tmp
  30 000a 85FD                  sbrc r24,5
  31                    .LM4:
  32 000c 9068                  ori r25,lo8(-128)
  33                    .L2:
  34                    .LM5:
  35 000e 9093 0000             sts command_rc5,r25
  36                    /* epilogue: frame size=0 */
  37 0012 0895                  ret
  38                    /* epilogue end (size=1) */
  39                    /* function foo size 11 (10) */

objdump erzeugt Disassemble

aus Object (nicht loakatiert)

Kommando:

> avr-objdump -d -S ...

Ausgabe:

00000000 <foo>:
uint8_t command_rc5, Ir_data_tmp; 

void foo()
{
   uint8_t cmd = command_rc5 & ~(1<<7);
   0:   90 91 00 00     lds     r25, 0x0000
   4:   9f 77           andi    r25, 0x7F       ; 127

   if (Ir_data_tmp & (1<<5))       
   6:   80 91 00 00     lds     r24, 0x0000
   a:   85 fd           sbrc    r24, 5
      cmd |= (1<<7);
   c:   90 68           ori     r25, 0x80       ; 128
   
   command_rc5 = cmd;   
   e:   90 93 00 00     sts     0x0000, r25
  12:   08 95           ret

aus elf (lokatiert)

Kommando:

> avr-objdump -h -S ...

Ausgabe:

0000005c <foo>:
uint8_t command_rc5, Ir_data_tmp; 

void foo()
{
   uint8_t cmd = command_rc5 & ~(1<<7);
  5c:   90 91 60 00     lds     r25, 0x0060
  60:   9f 77           andi    r25, 0x7F       ; 127

   if (Ir_data_tmp & (1<<5))       
  62:   80 91 61 00     lds     r24, 0x0061
  66:   85 fd           sbrc    r24, 5
      cmd |= (1<<7);
  68:   90 68           ori     r25, 0x80       ; 128
   
   command_rc5 = cmd;   
  6a:   90 93 60 00     sts     0x0060, r25
  6e:   08 95           ret

aus ihex (lokatiert)

Siehe auch


LiFePO4 Speicher Test