Forum: Mikrocontroller und Digitale Elektronik movlw: Berechnung des Literal


von Michael B. (auchduliebergott)


Lesenswert?

MPLAB, Assembler, PIC16F1512:

Warum funktioniert der folgende Ausdruck nicht?

[movlw  0x90+kanal-0x1]

Inhalt von "kanal" = 0x1
Adresse von "kanal" = 0x30

w soll geladen werden mit 0x90 + 0x1 - 0x1 = 0x90

Tatsächlich berechnet der Assembler diesen Wert aber mit 0xC0.
Statt den Inhalt der Zelle "kanal" zu nehmen, rechnet der Assembler wohl 
mit der Adresse der Zelle "kanal".
Wie erreiche ich das richtige Ergebnis?

von Motopick (motopick)


Lesenswert?

Da wird wohl ein intermediate '#' fehlen.
Ich empfehle da dringend das Studium der Adressierungsarten im Manual.

Ein movlw kann auch nicht auf:
> Inhalt von "kanal" = 0x1
zugreifen.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Wie hast Du denn kanal definiert?
Warum immer der Geiz mit dem Zeigen von den exakten Codezeilen (C&P).

von Michael B. (auchduliebergott)


Lesenswert?

Vielen Dank für die schnelle Information!

An welcher Stelle fehlt das #-Zeichen?

Wenn ich die Antwort richtig verstehe, dann kann ich mit oder ohne 
#-Zeichen keinesfalls auf den Inhalt von "kanal" zugreifen. Der 
Assembler rechnet immer nur mit der Adresse.

Zum Studium der Adressierungsarten: Ja, das ist notwendig, denn ich bin 
Anfänger...

von Michael B. (auchduliebergott)


Lesenswert?

Hallo peda,
"kanal" ist wie folgt am Anfang des Programmes dem Speicherort 0x30 
zugeordnet worden:
kanal  equ  0x30

von Peter D. (peda)


Lesenswert?

Ein Assemler kennt nicht das Konzept von Variablen, das kann nur ein 
Compiler.
Für den Assembler sind alle Symbole nur Symbole. Du kannst sie als 
Adreßlabel verwenden oder als Wert.

von Jens G. (jensig)


Lesenswert?

Michael B. schrieb:
> kanal  equ  0x30

Auch wenn meine PIC-Zeiten schon wieder ewig zurückliegen, aber das ist 
doch nur eine Konstante, und keine Adresse.

> Adresse von "kanal" = 0x30

von Peter D. (peda)


Lesenswert?

Michael B. schrieb:
> kanal  equ  0x30

Damit sagst Du dem Assembler nur, ersetze fürderhin alle Vorkommen von 
"kanal" durch "0x30".
Daß Du irgendwann mal an Adresse 0x30 den Wert 0x1 abspeichern willst, 
das kann er nicht erahnen.
Er weiß schlichtweg nichts von Variablen oder Typen.

von Michael B. (auchduliebergott)


Lesenswert?

Vielen Dank für den Hinweis.
Dann muss ich das wohl auflösen in folgende Programmzeilen:

  movlw  h'90'
  addwf  kanal,0    ;w = w + kanal (Inhalt von kanal)
  movwf  ON         ;ON = w
  decf   ON,1       ;ON = ON - 1

Schade, ich hatte geglaubt, dass man dies mit nur einer Zeile machen 
könnte:
        movlw  0x90+kanal-0x1

Jetzt sind es immerhin 4!

: Bearbeitet durch User
von Motopick (motopick)


Lesenswert?

addwf  kanal,0    ;w = w + kanal (Inhalt von kanal)

Das ist zwar nicht falsch, besser waere:
  addwf  kanal,w    ;w = w + kanal (Inhalt von kanal)

Dann ist der Kommentar unnoetig.

Genau so:
  decf   ON,1       ;ON = ON - 1

  decf   ON,f       ;ON = ON - 1 oder gleich
  decf   ON         ;ON = ON - 1

Das ein PIC kein ARM ist, hast du ja schon festgestellt.

Und sparen kann man beim PIC am besten, wenn man sich klar macht,
dass das w-Register eben kein Akku ist, sondern nur ein
Hilfsregister um literale Werte laden zu koennen.
Man rechnet eben direkt mit den Registern.
Das Ergebnis einer Operation steht danach im Register.
Weiteres Speichern: ueberfluessig.

von Michael B. (auchduliebergott)


Lesenswert?

Vielen Dank für die wertvollen Tipps. Dennoch habe ich noch folgende 
Fragen:

In der PIC-Befehlsbeschreibung steht aber, dass man "0" oder "1" hinter 
dem Komma schreiben soll, nicht aber "f", "w" oder gar "nichts"!
Das verwirrt natürlich den Laien und wirft die Frage auf, wo man 
nachlesen kann, welche Bezeichnungen hinter dem Komma zulässig sind.
In der Befehlsbeschreibung PIC kennt man nur "0" oder "1".
Ersetzt "f" die "1"? Ersetzt "w" oder " " die "0"?
Jedenfalls ist "f" oder "w" viel anschaulicher, als "0" oder "1"!

: Bearbeitet durch User
von Motopick (motopick)


Lesenswert?

> Jedenfalls ist "f" oder "w" viel anschaulicher, als "0" oder "1"!

Ja eben :).

Der Fall
> "nichts"
ist der Default. Und der steht sehr wohl in der Beschreibung.
Ob das f und w in den Assembler "eingebaut" ist, oder einfach
als EQU in einem Headerfile steht?
Das kannst du ja selbst rauskriegen.

Zum Lesen: https://www.sprut.de/electronic/pic/grund/grund.htm
https://www.sprut.de/electronic/pic/assemble/befehle.html

: Bearbeitet durch User
von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Michael B. schrieb:
> Schade, ich hatte geglaubt, dass man dies mit nur einer Zeile machen
> könnte:
>         movlw  0x90+kanal-0x1

Man muß sich schon mit dem Befehlssatz beschäftigen, wenn man Assembler 
programmieren will.

MOVLW erwartet eine Konstante als Argument. Es kann also keine Variable 
aus dem RAM lesen.
Der Assembler berechnet daher 0x90+0x30-0x1 und übergibt es dem MOVLW.

von Michael B. (auchduliebergott)


Lesenswert?

Vielen Dank für diese Informationen und die Zusammenhänge sind jetzt 
völlig klar.
Meine Bemerkung zum Befehlssatz und der "0" bzw. "1" bezog sich mehr auf 
den Befehl ADDWF, dessen Beschreibung wie folgt lautet:

ADDWF Add W and f
Syntax: [ label ] ADDWF f,d
Operands: 0  f  127
d 0,1
Operation: (W) + (f)  (destination)
Status Affected: C, DC, Z
Description: Add the contents of the W register
with register ‘f’. If ‘d’ is ‘0’, the result is
stored in the W register. If ‘d’ is ‘1’, the
result is stored back in register ‘f’.

Hier kann man für "d" gemäß Beschreibung nur "1" oder "0" einsetzen.
Von "w" oder "f" ist hier keine Rede.
Nach Deinen Erklärungen verstehe ich das wie folgt:
"0" würde dann "ADDWF xxx,w" entsprechen und "1" "ADDWF xxx,f".
"w" ist somit Platzhalter für "0" und "f" ist somit Platzhalter für "1".
Das dürfte im Assembler eingebaut sein, denn ansonsten bekäme ich eine 
Fehlermeldung bei Anwendung von "w" oder "f".

von Motopick (motopick)


Lesenswert?

> Das dürfte im Assembler eingebaut sein, denn ansonsten bekäme ich eine
> Fehlermeldung bei Anwendung von "w" oder "f".

Vermutlich ja.
Weil der Assembler ja auch ohne weitere Hilfe den Default kennt.
Trotzdem koennte "irgendwo" in einem Includefile ja auch ein:

f   EQU   1
w   EQU   0

stehen.
Das koenntest du zur Vervollstaendigung deines Wissens ja mal
ausprobieren. So ein EQU wuerde ja dann ueberall in einem
Assemblerfile seine Wirkung tun. Nicht nur in der Zielangabe
von Befehlen.

Also z.B.
   movlw   #f

:)

von Bernd M. (berndmm)


Lesenswert?

Michael B. schrieb:
> Vielen Dank für den Hinweis.
> Dann muss ich das wohl auflösen in folgende Programmzeilen:
>
>   movlw  h'90'
>   addwf  kanal,0    ;w = w + kanal (Inhalt von kanal)
>   movwf  ON         ;ON = w
>   decf   ON,1       ;ON = ON - 1
>
> Schade, ich hatte geglaubt, dass man dies mit nur einer Zeile machen
> könnte:
>         movlw  0x90+kanal-0x1
>
> Jetzt sind es immerhin 4!

Dass es 4 Zeilen sind, liegt daran, dass du das Ergebnis noch nach ON 
transportierst, sonst wären es 3 Zeilen. Man kann aber noch eine Zeile 
einsparen, wenn man nicht extra dekrementiert sondern:

movlw  0x90 - 0x01
addwf  kanal,w

von Michael B. (auchduliebergott)


Lesenswert?

Hallo motopick,

vermutlich findet man das im File "p16F1512" (include <p16F1512.inc>).
Leider kann ich diese Datei im MPLAB nicht öffnen.
Unter "Projects" ist dieses File nicht zu finden...

Noch einmal herzlichen Dank für Deine Zeit, die Du mit der Beantwortung 
meiner Fragen geopfert hast. Das hat mir deutlich weitergeholfen!

von H. H. (Gast)


Lesenswert?

Michael B. schrieb:
> vermutlich findet man das im File "p16F1512" (include <p16F1512.inc>).

So ist es:



;=====================================================================
;
;       Register Definitions
;
;=====================================================================

W                EQU  H'0000'
F                EQU  H'0001'

von Michael B. (auchduliebergott)


Lesenswert?

Hallo berndmm,

vielen Dank für Deinen heißen Tipp! Dann geht es ja doch erheblich 
kürzer (kanal=0x1):

    movlw  0x90-0x01       ;w = 0x8F
    addwf  kanal,w         ;w = 0x8F + kanal = 0x90

Das sind sogar 2 Zeilen weniger, wenn ich ON nicht brauche!
Wie konnte ich das übersehen?
Jetzt werde ich das gesamte Programm danach untersuchen, ob ich diesen 
Fehler auch noch woanders gemacht habe...
Herzlichen Dank!

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.