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
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".
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?
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
Disassembler: 94: 01 c0 rjmp .+2 96: 00 00 nop 98: fd cf rjmp .-6
das mit 1b und 1f ist legitim. kann sein, dass es ein reines gnu assembler ding ist.
Ohne diese Funktion sollte folgender Code identisch sein: start: rjmp bla nop bla: rjmp start blubb: rcall blink rjmp blubb
@ 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. :-)
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 |
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.
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"
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.
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.
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.