Forum: Mikrocontroller und Digitale Elektronik Sehr komisches AVR Assembler Problem. Nur drei Anweisungen!


von ASM Typ (Gast)


Lesenswert?

Hallo,

ich habe grad ein Projekt mit einem xmega E und habe einen komischen 
Fehler gesucht. Nach ewigem Runterbrechen und Wegkürzen blieb folgender 
Codeblock übrig:

2:
rjmp 1f
nop
1:
rjmp 2b

1:
rcall blink
rjmp 1b

Natürlich macht dieser Codeblock allein keinen Sinn, er ist halt 
runtergekürzt. Was erwartet man? Natürlich eine Endlosschleife. Was 
passiert? Der rjmp 2b Befehl wird einfach nicht ausgeführt. Er springt 
direkt in die nächste Anweisung. In diesem Fall fängt er an zu blinken.

Habe ich irgendwo einen Denkfehler? So schwer ist der Code nämlich 
nicht!

Ein work-around ist folgender:

2:
rjmp 1f
nop
1:
nop
rjmp 2b

von Grobi (Gast)


Lesenswert?

ASM Typ schrieb:
> 2:
> rjmp 1f
> nop
> 1:
> rjmp 2b
>
> 1:
> rcall blink
> rjmp 1b

ähh also assembler ist jetzt schon ein wenig was her, aber du siehst 
schon das du das label "1" hier mehrfach definiert hast? Schätze mal der 
compiler / assembler wird dir das "erste" label 1 "wegoptimieren".

von avr (Gast)


Lesenswert?

Grobi schrieb:
> Schätze mal der
> compiler / assembler wird dir das "erste" label 1 "wegoptimieren".

Nein das ist erlaubt. Mit f_orward und b_ackward wird die Sprungrichtung 
zum nächsten Label angegeben.

Was sagt denn das Disassembly?

von Grobi (Gast)


Lesenswert?

avr schrieb:
> Nein das ist erlaubt. Mit f_orward und b_ackward wird die Sprungrichtung
> zum nächsten Label angegeben.

... hmmm also grad mal probiert avr studio 4 ein asm test project:
1
two:
2
rjmp onef
3
nop
4
one:
5
rjmp twob
6
7
one:
8
rcall blink
9
rjmp oneb
10
11
blink:
12
nop
13
ret

->C:\mc\TestProjectASM001\main.asm(54): error: Duplicate label: 'one'
C:\mc\TestProjectASM001\main.asm(51): info: previous definition of 'one'

und nur die Zahl 1 oder 2 -> unexpected integer!

kann doch was nicht so wirklich richtig sein

von ASM Typ (Gast)


Lesenswert?

Disassembler:

  94:       01 c0           rjmp    .+2
  96:       00 00           nop
  98:       fd cf           rjmp    .-6

von ASM Typ (Gast)


Lesenswert?

das mit 1b und 1f ist legitim. kann sein, dass es ein reines gnu 
assembler ding ist.

von ASM Typ (Gast)


Lesenswert?

Ohne diese Funktion sollte folgender Code identisch sein:

start:
rjmp bla
nop
bla:
rjmp start

blubb:
rcall blink
rjmp blubb

von Theor (Gast)


Lesenswert?

@ ASM Typ

Hm. Laut der GNU Assemblerbeschreibung sollte der Code so ablaufen, wie 
Du es im ersten Post beschrieben hast.

Du könntest Dir ja mal den Assembleroutput (also das Listing) anschauen, 
ob der GNU AS das auch wie beschreiben in nicht-lokale Labels umsetzt. 
Vielleicht ist das ja nur ein Bug in einer bestimmten Version.


P.S. Es juckt mich, noch ein persönliche Wertung dieses "Features" 
hinzuzufügen. Aber die Anführungszeichen sollen hier mal reichen. :-)

von Grobi (Gast)


Lesenswert?

1
start:
2
rjmp bla
3
nop
4
bla:
5
rjmp start
6
7
blubb:
8
rcall blink
9
rjmp blubb
10
11
blink:
12
nop
13
ret

->

---- main.asm 
------------------------------------------------------------------------ 
-------------
1
44:       rjmp bla
2
+00000020:   C001        RJMP      PC+0x0002      Relative jump
3
45:       nop
4
+00000021:   0000        NOP                      No operation
5
@00000022: bla
6
47:       rjmp start
7
+00000022:   CFFD        RJMP      PC-0x0002      Relative jump
8
@00000023: blubb
9
50:       rcall blink
10
+00000023:   D001        RCALL     PC+0x0002      Relative call subroutine
11
51:       rjmp blubb
12
+00000024:   CFFE        RJMP      PC-0x0001      Relative jump
13
@00000025: blink
14
54:       nop
15
+00000025:   0000        NOP                      No operation
16
55:       ret
17
+00000026:   9508        RET                      Subroutine return

von fop (Gast)


Lesenswert?

hm, was kommt vor dem ausgelassenen Jump ?
Es gibt nämlich so was wie 'skip if' in AVR Assembler. Das bewirkt, dass 
unter festgelegten Umständen der folgende Befehl nicht ausgeführt wird.
Möglicherweise steht auch direkt vor dem Jump ein halber 2-Byte-Befehl, 
so dass der Jump nicht als solcher, sondern als 2. Hälfte des 
vorhergehenden Befehls interpretiert wird.

von Axel S. (a-za-z0-9)


Lesenswert?

Grobi schrieb:
> kann doch was nicht so wirklich richtig sein

Ja. Der Fehler ist, daß du einen anderen Assembler verwendest.

Siehe 
https://sourceware.org/binutils/docs/as/Symbol-Names.html#Symbol-Names 
unter "Local Labels"

von M. Н. (Gast)


Lesenswert?

ASM Typ schrieb:
> Natürlich macht dieser Codeblock allein keinen Sinn, er ist halt
> runtergekürzt. Was erwartet man? Natürlich eine Endlosschleife.

Ich kann dieses Verhalten mit deinem geposteten Code nicht 
nachproduzieren. Kann allerdings auch daran liegen, dass ich die 
Label-Namen geändert habe, da ich nicht den GNU-Assembler verwende. Bei 
mir sieht der produzierte Binärcode genau so aus wie bei "Grobi (Gast)" 
und funktioniert auch.

Hast du es mal mit anderen Labels probiert?
Es gibt zwei Möglichkeiten:
1) Du hast einen Assemberlfehler entdeckt.
2) Dein Code ist anders als dargestellt.

Das dekompilierte Assembler-Listing in Kombination mit dem verwendeten 
Source-Code würde, wie bereits gesagt, helfen.

von ASM Typ (Gast)


Lesenswert?

Ich habe es bereits mit festen Labels versucht. Der Codeblock wird 
zuverlässig immer übersprungen. Getestet habe ich es aber nur auf dem 
xmega E.

von ASM Typ (Gast)


Lesenswert?

Ich habe auch ein neues Projekt gemacht, nur mit diesem Code. Nach dem 
Code dann ein sbi als Kontrollfunktion. Auch hier wird der Codeblock 
immer übersprungen...

von Axel S. (a-za-z0-9)


Lesenswert?

Da ergibt alles keinen Sinn. Der gezeigte Code
1
2:
2
    rjmp 1f
3
    nop
4
1:
5
    rjmp 2b

ergibt - mit dem GNU Assembler für AVR assembliert - zweifellos eine 
Endlosschleife. Mit einen anderen Assembler dürfte er gar nicht 
assemblierbar sein.

So sieht es bei mir aus:
1
/tmp $cat test.S
2
        .section .text
3
        .org 0
4
2: 
5
        rjmp 1f
6
        nop
7
1: 
8
        rjmp 2b
9
/tmp $avr-gcc -o test.elf test.S
10
/tmp $avr-objdump -d test.elf 
11
12
test.elf:     file format elf32-avr
13
14
15
Disassembly of section .text:
16
17
00000000 <__ctors_end>:
18
   0:   01 c0           rjmp    .+2             ; 0x4 <__ctors_end+0x4>
19
   2:   00 00           nop
20
   4:   fd cf           rjmp    .-6             ; 0x0 <__ctors_end>

Ganz klar eine Endlosschleife. Das erste rjmp springt zu Adresse 4, das 
zweite zurück zu Adresse 0.

Also: wo kommt der gezeigte Code her? Wie hast du die Funktion getestet?

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
Noch kein Account? Hier anmelden.