Forum: Mikrocontroller und Digitale Elektronik Operand 2 Out Of Range


von Gast (Gast)


Lesenswert?

Kann mir bitte einer sagen warum dieses Programm sich nicht Assemblieren 
lässt?

Es erscheint immer der Fehler "Operand 2 Out Of Range". Kann diesen 
Fehler jemand beheben?

mfg.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;;;;;

.include "m8def.inc"

  ldi r16, 0xff
  out DDRB, r16

  ldi r16, 0x00
  out PortB, r16

  out DDRC, r16
  out PortC, r16

  ldi r16, LOW(RAMEND)
  out SPL, r16
  ldi r16, HIGH(RAMEND)
  out SPH, r16

;
;:::::::::::::Timerwahl::::::::::::
;

loop:
  sbis PortC, 0b00000001
  rjmp Timer1

  sbis PortC, 0b00000010
  rjmp Timer2

  sbis PortC, 0b00000100
  rjmp Timer3

  sbis PortC, 0b00001000
  rjmp Timer4

  sbis PortC, 0b00010000
  rjmp Timer5

  rjmp loop

;
;::::::::::::::Timer:::::::::::::
;

Timer1:
  sbis PortC, 0b00100000
  rjmp Timer1A
  rjmp Timer1

Timer2:
  sbis PortC, 0b00100000
  rjmp Timer2A
  rjmp Timer2

Timer3:
  sbis PortC, 0b00100000
  rjmp Timer3A
  rjmp Timer3

Timer4:
  sbis PortC, 0b00100000
  rjmp Timer4A
  rjmp Timer4

Timer5:
  sbis PortC, 0b00100000
  rjmp Timer5A
  rjmp Timer5

;
;:::::::Ausführen:::::::::::::::
;

Timer1A:
  ldi r16, PortC
  push r16

  ldi r16, 0b00000001
  out PortB, r16

;::::::::Zeitschleife einfügen:::::::
  ldi  R17, $BF
WGLOOP01:
  ldi  R18, $A7
WGLOOP11:
  ldi  R19, $D0
WGLOOP21:
  dec  R19
    brne WGLOOP21
    dec  R18
    brne WGLOOP11
    dec  R17
    brne WGLOOP01
    ldi  R17, $02
WGLOOP31:
  dec  R17
    brne WGLOOP31
    nop
    nop
;::::::::::::::::::::::::::::::::::::::::

  pop r16
  out PortC, r16
  rjmp Timer1


Timer2A:
  ldi r16, PortC
  push r16

  ldi r16, 0b00000001
  out PortB, r16

;::::::::Zeitschleife einfügen:::::::
  ldi  R17, $BF
WGLOOP02:
  ldi  R18, $A7
WGLOOP12:
  ldi  R19, $D0
WGLOOP22:
  dec  R19
    brne WGLOOP22
    dec  R18
    brne WGLOOP12
    dec  R17
    brne WGLOOP02
    ldi  R17, $02
WGLOOP32:
  dec  R17
    brne WGLOOP32
    nop
    nop
;::::::::::::::::::::::::::::::::::::::::

  pop r16
  out PortC, r16
  rjmp Timer2


Timer3A:
  ldi r16, PortC
  push r16

  ldi r16, 0b00000001
  out PortB, r16

;::::::::Zeitschleife einfügen:::::::
  ldi  R17, $BF
WGLOOP03:
  ldi  R18, $A7
WGLOOP13:
  ldi  R19, $D0
WGLOOP23:
  dec  R19
    brne WGLOOP23
    dec  R18
    brne WGLOOP13
    dec  R17
    brne WGLOOP03
    ldi  R17, $02
WGLOOP33:
  dec  R17
    brne WGLOOP33
    nop
    nop
;::::::::::::::::::::::::::::::::::::::::

  pop r16
  out PortC, r16
  rjmp Timer3


Timer4A:
  ldi r16, PortC
  push r16

  ldi r16, 0b00000001
  out PortB, r16

;::::::::Zeitschleife einfügen:::::::
  ldi  R17, $BF
WGLOOP04:
  ldi  R18, $A7
WGLOOP14:
  ldi  R19, $D0
WGLOOP24:
  dec  R19
    brne WGLOOP24
    dec  R18
    brne WGLOOP14
    dec  R17
    brne WGLOOP04
    ldi  R17, $02
WGLOOP34:
  dec  R17
    brne WGLOOP34
    nop
    nop
;::::::::::::::::::::::::::::::::::::::::

  pop r16
  out PortC, r16
  rjmp Timer4


Timer5A:
  ldi r16, PortC
  push r16

  ldi r16, 0b00000001
  out PortB, r16

;::::::::Zeitschleife einfügen:::::::
  ldi  R17, $BF
WGLOOP05:
  ldi  R18, $A7
WGLOOP15:
  ldi  R19, $D0
WGLOOP25:
  dec  R19
    brne WGLOOP25
    dec  R18
    brne WGLOOP15
    dec  R17
    brne WGLOOP05
    ldi  R17, $02
WGLOOP35:
  dec  R17
    brne WGLOOP35
    nop
    nop
;::::::::::::::::::::::::::::::::::::::::

  pop r16
  out PortC, r16
  rjmp Timer5

von Karl H. (kbuchegg)


Lesenswert?

> Es erscheint immer der Fehler "Operand 2 Out Of Range".
> Kann diesen Fehler jemand beheben?

Wie wärs mit dir selber?

Bei einer Fehlermeldung steht immer die Zeilennummer dabei.
Dann suchst du im Quelltext besagt Zeile und siehst nach bei welcher
Operation das ist. Wenn du die Operation hast, schaust du in der Doku 
(entweder online-Doku oder heruntergeladene Papierdoku) nach, welche 
Einschränkungen für den Operanden 2 in besagtem Befehl gelten. Und dann 
vergleichst du das mit dem was du hast.

von mr. Tannnoy (Gast)


Lesenswert?

Ich kenne Deine Programmierumgebung nicht, aber:

Die Meldung müsste eigentlich eine Zeilennummer enthalten.

Dort muss der 2. Operand überprüft werden

Ich vermute mal, Du hast einen 16-Bit Operanden genommen, wo nur 8 Bit 
gehen.

Viel Spaß beim Suchen. Wird nicht so schlimm sein!

von (prx) A. K. (prx)


Lesenswert?

Nebenbei:
  ldi r16, PortC
  push r16
  ...
  pop r16
  out PortC, r16
ist nicht ganz das, was dir dabei vorschwebt.

von Johannes M. (johnny-m)


Lesenswert?

Du solltest Dir in der Befehlssatzdokumentation mal ansehen, was für 
Operanden der Befehl sbis erwartet.

Kleiner Tip: Der zweite Operand muss im Bereich 0...7 liegen! 0b00100000 
ist aber deutlich außerhalb davon...

von Gast (Gast)


Lesenswert?

So hab das Programm neu geschrieben!
Nun funktioniert es!

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.include "m8def.inc"

ldi r16, 0xff
out ddrb, r16

ldi r16, 0x00
out ddrc, r16
out portc, r16

ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16

;
;:::::::::::::::::::Timerwahl::::::::::::
;

PortEinlesen:
  in r16, pinc

Timer1:
   cpi r16,0b00000010
    brne Timer2
   rjmp Timer1W

Timer2:
    cpi r16,0b00000100
    brne Timer3
   rjmp Timer2W

Timer3:

    cpi r16,0b00001000
    brne Timer4
   rjmp Timer3W

Timer4:
    cpi r16,0b00010000
    brne Timer5
   rjmp Timer4W

Timer5:

    cpi r16,0b00100000
    brne PortEinlesen
   rjmp Timer5W

;
;::::::Auf Befehl warten:::::::::::::
;

Timer1W:
  sbic pinc, 0b00000001
  rjmp Timer1A
  rjmp Timer1W

Timer2W:
  sbic pinc, 0b00000001
  rjmp Timer2A
  rjmp Timer2W

Timer3W:
  sbic pinc, 0b00000001
  rjmp Timer3A
  rjmp Timer3W

Timer4W:
  sbic pinc, 0b00000001
  rjmp Timer4A
  rjmp Timer4W

Timer5W:
  sbic pinc, 0b00000001
  rjmp Timer5A
  rjmp Timer5W

;
;::::::::::::::Ausführen:::::::::::::
;

Timer1A:
  in r16, pinc
  push r16
  ldi r16, 0b00000001
  out portb, r16

;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::

  pop r16
  out portc, r16
  rjmp Timer1W

Timer2A:
  in r16, pinc
  push r16
  ldi r16, 0b00000001
  out portb, r16

;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::

  pop r16
  out portc, r16
  rjmp Timer2W

Timer3A:
  in r16, pinc
  push r16
  ldi r16, 0b00000001
  out portb, r16

;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::

  pop r16
  out portc, r16
  rjmp Timer3W

Timer4A:
  in r16, pinc
  push r16
  ldi r16, 0b00000001
  out portb, r16

;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::

  pop r16
  out portc, r16
  rjmp Timer4W

Timer5A:
  in r16, pinc
  push r16
  ldi r16, 0b00000001
  out portb, r16

;::::::::::Zeitschleife hier einfügen::::::::
nop
;::::::::::::::::::::::::::::::::::::::::::::

  pop r16
  out portc, r16
  rjmp Timer5W

von Johannes M. (johnny-m)


Lesenswert?

> sbic pinc, 0b00000001
Immer noch nicht kapiert? sbis und sbic erwarten als zweiten 
Operanden keine Bitmaske, sondern die Bitnummer! Und eine Nummer 
schreibt man nicht im Binärformat! Du verwechselst das mit sbrs und 
sbrc, bei denen braucht's ne Bitmaske.

Außerdem steht in den Forenregeln klipp und klar, dass längerer Code als 
Anhang gepostet werden soll und nicht im Thread! Und es gibt hier auch 
die Möglichkeit, Code so zu formatieren, dass er besser als solcher 
erkennbar und auch besser lesbar ist! Und die Möglichkeit sollte man 
auch nutzen...

von Gast (Gast)


Angehängte Dateien:

Lesenswert?

So besser?
schuldigung das ich hier gegen Regeln verstoßen habe!

von Karl H. (kbuchegg)


Lesenswert?

Im Prinzip ja.

Was soll das Programm eigentlich machen?
Dein Programm sieht etwas seltsam aus.

zb. sind alle TimerxA identisch (oder hab ich da was übersehen)
1
Timer5A:
2
  in r16, pinc
3
  push r16
4
  ldi r16, 0b00000001
5
  out portb, r16
6
7
;::::::::::Zeitschleife hier einfügen::::::::
8
nop
9
;::::::::::::::::::::::::::::::::::::::::::::
10
11
  pop r16
12
  andi r16, 0b11111110
13
  out portc, r16
14
  rjmp Timer5W

Die Sequenz von PINC einzulesen und dann das Gelesene (ausser Bit0) auf 
dem PORTC auszulesen, sieht mehr überhaupt nicht koscher aus. 
Letztendlich bedeutet das doch, dass du alle Pins (ausser Pin 0) sowohl 
als Eingang als auch als Ausgang ansiehst (bzw. dort die Pullups von 
Eingangspins umschaltest).

Das ganze ist mehr als undurchsichtig (oder ich bin einfach schon müde). 
Ich denke mal, das kann man auch wesentlich einfacher machen.

von Hannes Lux (Gast)


Lesenswert?

> Ich denke mal, das kann man auch wesentlich einfacher machen.

Richtig. Aber dazu müsste der "Autor" sein Programm verstehen. Dies 
scheint hier nicht der Fall zu sein, ich vermute, dass hier 
unverstandener fremder Code zusammenkopiert, dupliziert und 
verschlimmbessert wurde.

...

von Gast (Gast)


Lesenswert?

Nope

Das is eigenentwicklung!
Die Timer sind gleich weil man einen Timer seiner Wahl reinmachen kann.
Habe nur ein nop drinne weil es sich so besser simulieren ließ!

Also wenns interressiert .... bei Conrad gibt es ein Bausatz mit dem man 
über einen LDR ein Relais bestimmte zeit lang anschalten und dann wieder 
aus schalten kann.
Ich will diesen selbst bauen und ein paar extras noch!

Aber abwarten wenn ich heute aufm stk getestet hab stell ich schaltplan 
noch rein und dann seht ihrs!

Also geht mal an alle hier .. nicht immer mit ngativen kommentaren 
kommen wenn anfänger hier mal ein Code posten!!!!
Auch wenn sie oft fehler beinhalten!!!!

von Hannes Lux (Gast)


Lesenswert?

Gut, dann ist es Eigenbau, den Begriff "Entwicklung" lasse ich mal außen 
vor, denn bis zu diesem Stadium fließt noch allerhand Wasser den Rhein 
hinunter...

Ich habe mich nicht intensiv mit Deinem Code auseinandergesetzt, weil 
ich ihn beim groben Ansehen als sehr uneffizient eingestuft habe, was 
wohl in den vielen Wiederholungen gleicher Sequenzen, dem Fehlen einer 
Tastenentprellung und dem Vermeiden von Interrupt oder zumindest 
Unterprogramm-Aufruf begründet ist. Gut, es ist ein Anfängerprogramm, 
aber in einer Anfängerphase, wo es noch um das Lernen geht und noch 
nicht um das Realisieren von Projekten. Der nächste Lernschritt wäre 
dann das Verwenden eines Unterprogramms für die Warteschleife, die Du 
fälschlicherweise "Timer" nennst. Und dann sollte die Erkenntnis kommen, 
dass Du beim Mega8 drei Hardware-Timer mitbezahlt hast, von denen einer 
reicht, Dir im Hintergrund (also durch Hardware) einen "langsamen" 
Zeittakt zu generieren, der Dein gesamtes Programm synchronisiert und 
Warteschleifen unnötig macht. Wenn dann noch die Notwendigkeit einer 
soliden Tastenentprellung mit Flankenerkennung erkannt und realisiert 
wurde, dann kann man langsam über die Realisierung von Projekten 
nachdenken. Nein, ich will es Dir nicht mies reden, Du bist schon auf 
dem richtigen Weg, aber eben noch ganz am Anfang. Der Weg ist weiter als 
Du jetzt vermutest. Noch kämpfst Du mit dem Alphabet (Befehlssatz, 
erlaubte Register und Bereiche), also mit Selbstverständlichkeiten der 
AVR-Architektur, später wirst Du Dich dann damit beschäftigen, welche 
Algorithmen die Richtigen sind und wie man sie halbwegs effizient in 
Assembler formuliert.

Vielleicht solltest Du nebenher auch mal schaun, wie es Andere machen. 
Dazu bieten sich diverse Tutorials an, z.B. das auf dieser Seite oder 
das AVR-ASM-Tutorial:
http://www.mikrocontroller.net/articles/AVR-Tutorial
http://www.avr-asm-tutorial.net/
Weiterhin bieten sich die Projekte Anderer in der Codesammlung an:
http://www.mikrocontroller.net/forum/codesammlung
Durch Analyse einzelner Codesequenzen und Vergleich mit eigenem Code für 
ähnliche Aufgaben kommt so manche Erkenntnis ganz von alleine, ohne dass 
man mehrere "persönliche Berater" beschäftigen muss.

Noch'n Tip:
Drucke Dir aus dem Datenblatt die Tabelle mit dem Befehlssatz aus. Mit 
dieser Übersicht und der Hilfe zum AVR-Studio geht das Erlernen des 
Befehlssatzes bedeutend besser und schneller. Gleiches gilt auch für die 
Tabelle mit der Beschreibung der I/O-Register. Diese ist sehr hilfreich 
beim Nachschlagen der Namen der I/O-Register und ihrer Bits, und dient 
dank der Angabe der Seiten-Nummern auch noch als Inhaltsverzeichnis zum 
Datenblatt-PDF. Dies spart (gerade in der Lernphase) allerhand Zeit und 
Frust.

...

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:

> Also geht mal an alle hier .. nicht immer mit ngativen kommentaren
> kommen wenn anfänger hier mal ein Code posten!!!!

Darum gehts nicht.

Aber so wie das Programm aussieht, wärs vielleicht mal ganz gut, wenn 
dir jemand mit mehr Erfahrung zeigt, wie man das einfacher machen kann. 
Du willst ja auch was dabei lernen.

von Gast (Gast)


Lesenswert?

Danke Hannes Lux!
Ich werde mich daran machen das von dir beschriebene mir anzueigenen!


DIESER THREAD KANN GECLOSED WERDEN!!!
Es steht nichts nütliches darin...

von Hannes Lux (Gast)


Lesenswert?

> DIESER THREAD KANN GECLOSED WERDEN!!!

Glücklicherweise bestimmst Du das nicht.

Dieser Thread kann nämlich immer noch als Beispiel für den nächsten 
Anfänger dienen, der da meint, statt eigener Recherche ein halbes 
Dutzend Helfer beschäftigen zu müssen.

...

von Sven P. (Gast)


Lesenswert?

Johannes M. wrote:
>> sbic pinc, 0b00000001
> Immer noch nicht kapiert? sbis und sbic erwarten als zweiten
> Operanden keine Bitmaske, sondern die Bitnummer! Und eine Nummer
> schreibt man nicht im Binärformat! Du verwechselst das mit sbrs und
> sbrc, bei denen braucht's ne Bitmaske.

Nö, auch sbrc und sbrs wollen eine Bit-NUMMER.
Den Unterschied, den du vermutlich meinst, betrifft cbi/sbi und cbr/sbr. 
/cbi und sbi erwarten eine Bitnummer, wohingegen sbr ein Alias für 
ori ist und genauso wie sbr eine Maske sehen will.

von Johannes M. (johnny-m)


Lesenswert?

Sven P. wrote:
> Nö, auch sbrc und sbrs wollen eine Bit-NUMMER.
> Den Unterschied, den du vermutlich meinst, betrifft cbi/sbi und cbr/sbr.
> /cbi und sbi erwarten eine Bitnummer, wohingegen sbr ein Alias für
> ori ist und genauso wie sbr eine Maske sehen will.
Jou, da haste wahr. Ich wollte noch zur Sicherheit eben nachschauen, hab 
das dann aber irgendwie nicht mehr gemacht...

von Gast3 (Gast)


Lesenswert?

Was auch noch auf den ersten Blick auffaellt, ist das Fehlen jeglicher 
Kommentare.

Gast3

von Hannes Lux (Gast)


Lesenswert?

> Was auch noch auf den ersten Blick auffaellt, ist das Fehlen jeglicher
> Kommentare.

Ja, schon, aber diesen Satz habe ich mir verkniffen, da der Quelltext 
viele Trennzeilen aus Doppelpunkten enthält, die man evtl. als 
Kommentare bezeichnen kann. Und über den Sinn oder Unsinn dieser 
Kommentarzeilen möchte ich nicht diskutieren, da es schwer ist, die 
richtige Menge zu finden. Bei zuwenig geht die Formatierung verloren, 
bei zuviel ist auf dem Bildschirm zuwenig Platz für den eigentlichen 
Quelltext.

Aber irgendwie habe ich noch nicht gerafft, was das Programm eigentlich 
mal tun soll. Die Aufgaben (Conrad-LDR-Relais) sind mir irgendwie nicht 
konkret genug formuliert. Daher kann ich auch nicht helfen, das Programm 
zu optimieren. Der wichtigste und aufwändigste Schritt bei der 
Entwicklung eines Programmes ist nunmal die eindeutige 
unmissverständliche Beschreibung der zu lösenden Aufgabe (mit normalen 
Worten, also ohne Einsatz einer Programmiersprache). Solange dies nicht 
klar definiert ist, lohnt es sich nicht, über die Programmierung in 
einer Programmiersprache nachzudenken.

...

von Philipp P. (-crack-)


Lesenswert?

Hallo Gast,
meine Vorredner haben ja schon gesagt, das es in deinem Programm noch 
sehr viele Fehler gibt und vorallem UNGEREIMTHEITEN!

Ich habe mich mal bei Conrad umgeschaut und ich glaube ich habe gefunden 
was du suchst .... Conrad Artikel-Nr.: 190951 - 62
Oder nicht?

Dieser Bausatz sieht sehr interessant aus aber ist schwer realisierbar.
Also für einen Anfänger! Wenn du möchtest könnte ich dir unter die Arme 
greifen :)
Denn ich finde dieses Modul äuserst interessant ;)

mfg. -crack-

von Philipp P. (-crack-)


Lesenswert?

So dein Programm ist nicht klar strukturiert aber ich denke wenn man es 
kommentiert wird es klarer, deshalb werde ich den ansatz so belassen und 
nur schnell ein paar Änderungen vornehmen!

Schau doch einfach mal im AVR Tutorial unter Tasten nach ... da ist ein 
Beispiel von Peter Dannegger. Dieses werde ich aus Zeitgründen 1:1 
übernehmen. Aber dafür sind Beispiele ja da ;)

Das mit dem Timer musst du selbst programmieren, da ich wirklich wenig 
Zeit habe und dies nun nebenbei mache ....

Bis heute abend sollte es fertig sein ....

Ihr anderen haut mich nicht weil ich seine unübersichtliche Struktur 
lasse ;)

von Philipp P. (-crack-)


Angehängte Dateien:

Lesenswert?

Sodale das Programm ist fertig ...

Ich hab die Idee mit diesen Kommentar "Überschriften" beibehalten :) ist 
irgendwie witzig ;)

Hoff das ist das was du versucht hast zu programmieren ....

Du musst jetzt nurnoch die Timer einfügen, da wo das Programm dann 
einfach irgendwelche Werte an PortB ausgibt ... also bei 
Timer1A-Timer5A!
Hab die ausgaben nur zum testen azfm stk reingemacht ....
Wenn dir Timer zu schwer sind, dann nimm delay-loops. Aber das sollte 
nur eine Notlösung sein, denn elegant ist das nicht!!!

mfg. -crack-

von Gast (Gast)


Lesenswert?

Danke für das Programm -crack-!

Funktioniert einwandfrei!
Aber nehme Delay schleifen da ich keine Timer programmieren kann.

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.