GNU Assembler erzeugt Label mit nicht druckbaren Zeichen?

Persönliche Seite #7423007
Lesenswert?

Folgendes C-Modul:

1
void callee (int*);
2

3
void func (void)
4
{
5
    int i;
6
    callee (&i);
7
}

Das compilieren und disassemblieren:

1
$ avr-gcc -mmcu=atmega8 frame.c -Os -c && avr-objdump -d frame.o
2

3
[...]
4
00000000 <func>:
5
   0:  cf 93         push  r28
6
   2:  df 93         push  r29
7
   4:  00 d0         rcall  .+0        ; 0x6 <L0^A>
8

9
00000006 <L0^A>:
10
   6:  cd b7         in  r28, 0x3d  ; 61
11
   8:  de b7         in  r29, 0x3e  ; 62
12
   a:  ce 01         movw  r24, r28
13
   c:  01 96         adiw  r24, 0x01  ; 1
14
   e:  00 d0         rcall  .+0        ; 0x10 <L0^A+0xa>
15
  10:  0f 90         pop  r0
16
  12:  0f 90         pop  r0
17
  14:  df 91         pop  r29
18
  16:  cf 91         pop  r28
19
  18:  08 95         ret

Nach dem "rcall .", das 2 Byte Stack für i allokiert, fügt der Assembler ein Label mit dem nicht druckbaren Zeichen ^A ein. Die Länge des Labels / Symbols "L0^A" ist 3 Bytes.

Assembliert wurde mit Binutils 2.40.

Kann jemand sagen, wozu das gut ist? Ältere Binutils-Versionen machen das nicht. Je nach Quelle gibt's mehrfach das gleiche Label, ohne dass es irgendwelche Probleme zu machen scheint.

Das vom Compiler generierte Assembly enthält natürlich kein solches Label:

1
func:
2
  push r28
3
  push r29
4
  rcall .
5
  in r28,__SP_L__
6
  in r29,__SP_H__
7
  ...
Persönliche Seite #7423033
Lesenswert?

Norbert schrieb:

Johann L. schrieb:

fügt der Assembler ein Label mit dem nicht druckbaren Zeichen ^A ein.

Hab' ich schon mal im GNU Assembler Manual gelesen. Ergab sogar Sinn… ;-)

https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_5.html#SEC46

1
C-A
2
    This unusual character is included so you do not accidentally
3
    invent a symbol of the same name. The character has ASCII value `\001'.

Ok, das wird so gemacht für lokale Label wie "0:", es wird aber nicht erklärt, warum der Assembler selbsttätig Labels einfügt, die nicht in der Quelle stehen.

Das "L0^A" wird zum Beispiel von GAS v2.40 eingefügt.

GAS v2.28 fügt es nicht ein. Die Doku ist zu GAS v2.9.

Persönliche Seite #7423042
Lesenswert?

...für lokale Label ist das Verhalten auch anders:

1
void llabel (void)
2
{
3
    __asm ("rjmp 0f $ break $ 0:");
4
}

v2.28 disassembliert (GAS mit sowie ohne -L) zu:

1
0000001c <llabel>:
2
  1c:  00 c0         rjmp  .+0        ; 0x1e <llabel+0x2>
3
      1c: R_AVR_13_PCREL  .text+0x20
4
  1e:  98 95         break
5
  20:  08 95         ret

v2.40 disassembliert (GAS mit sowie ohne -L) zu:

1
0000001c <llabel>:
2
  1c:  00 c0         rjmp  .+0        ; 0x1e <llabel+0x2>
3
      1c: R_AVR_13_PCREL  .L0^B1
4
  1e:  98 95         break
5

6
00000020 <.L0^B1>:
7
  20:  08 95         ret

v2.28 erzeugt also kein Label für "0:" und berechnet einfach nur den Offset.

v2.40 erzeugt ein Label mit ^B wie in der Doku beschrieben. Hatten die Autoren der Doku zu v2.9 damals ne Zeitmschine, um v2.40 vorherzusagen?

Meine Verwirrung wird irgendwie nicht kleiner.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren