Forum: Mikrocontroller und Digitale Elektronik ADD und ADC Befehl, Frage zur Rechnung


von Mike (Gast)


Lesenswert?

Hallo Zusammen,
habe eine Frage zu den oben genannten Befehlen und zwar folgendes:

R1 = 0xfe
R2 = 0x03
Carry = 0
Z = 0
N = 1
V = 1
-----------------------------
Nun word folgendes ausgeführt: adc R1, R2

Als Ergebnis kommt 0x01 raus, aber ich möchte verstehen wie das 
funktioniert, Der ADC Befehl addiert R1 und R2 miteinander. Aber wie 
wird das Carry dazugerechnet? Wird es sozusagen dazuaddiert, dann würde 
aber nicht 0x01 rauskommen. ODer addiert man R1 und R2 und schaut dann, 
ob dann nach der Rechnung eine 1 davor ist oder nicht? Oder hängt das 
damit zusammen, ob vorher das Carryfalg auf 0 wir in diesem Beispiel ist 
oder auf 1.

Und was passiert bei add Befehl, wenn es zum Überlauf kommt, also was 
würde für R1 herauskommen, wenn es add statt adc währe und wie würden 
die Flags danach aussehen?

Danke vorab!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mike schrieb:

> Aber wie
> wird das Carry dazugerechnet? Wird es sozusagen dazuaddiert, dann würde
> aber nicht 0x01 rauskommen.

Doch, denn Carry ist ja (im Moment) 0.  Es wird das Carryflag dazu
addiert, wie es vor der Rechnung existierte.

Dein gedankliches Problem liegt darin, dass die beiden Additionen
nicht nacheinander erfolgen, sondern praktisch gleichzeitig, d. h.
du hast einen Addierer mit drei Eingängen, von denen der dritte (das
Input-Carry) jedoch nur 1 Bit breit ist.

Nach der Operation wird dann der Zustand des Output-Carry in das
Carry-Flag des Prozessors übertragen.

(Selbst, falls die Operation in der Tat im Prozessor sequentiell
ausgeführt wird, dann wird durch Synchronisation sichergestellt,
dass das Input-Carry sich währed der Operation nicht mehr ändert.)

> Und was passiert bei add Befehl, wenn es zum Überlauf kommt, also was
> würde für R1 herauskommen, wenn es add statt adc währe und wie würden
> die Flags danach aussehen?

Die Flags würden ganz genauso aussehen.  Die ADC-Operation unterscheidet
sich von ADD nur dann, wenn vorher das Carry-Flag ungleich 0 war.
ADD ignoriert in diesem Falle das Carry-Flag, ADC würde es mit
einbeziehen.

Die übliche Folge zum Addieren von Zahlen, die größer als die
Wortbreite des Prozessors sind, ist daher:
1
ADD R8, R4  ; hier interessiert der Zustand des Carry-Flags nicht,
2
            ; aber es wird durch die Operation gesetzt oder gelöscht
3
ADC R9, R5
4
ADC R10, R6
5
ADC R11, R7 ; das Output-Carry dieser Operation wird dann meist
6
            ; ignoriert

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

Hallo,

der ADC-Befehl addiert einfach die beiden Werte. Wenn aber VOR dem 
Befehl das Carry-Flag gesetzt war, wird es auch noch dazuaddiert.

R1 = 0xfe
R2 = 0x03
C  = 0
Ergebnis: 0x01, C = 1

R1 = 0xfe
R2 = 0x03
C  = 1
Ergebnis: 0x02, C = 1

Oder so:

R1 = 0x01
R2 = 0x02
C  = 1
Ergebnis: 0x04, C = 0


ADD ignoriert das Carry-Flag.

R1 = 0xfe
R2 = 0x03
C  = 0
Ergebnis: 0x01, C = 1

R1 = 0xfe
R2 = 0x03
C  = 1
Ergebnis: 0x01, C = 1

R1 = 0x01
R2 = 0x02
C  = 1
Ergebnis: 0x03, C = 0


Gruß
Jonathan

von Mike (Gast)


Lesenswert?

Genau so habe ich es auch verstanden.

Wenn Carryflag anfangs Null bei ADC, dann rechne ich normal, also beide 
addieren und wenn es dann nach der Rechnung eine 1 davor steht z.B. f+1, 
dann wird Carryflag 1 gesetzt.

Falls Carryflag vor der Rechnung 1 gesetzt ist, wird die 1 dazuaddiert 
... also +1 und dann ist das Carryflag nach der Rechnung immer noch 
gesetzt, richtig?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Mike schrieb:
> und dann ist das Carryflag nach der Rechnung immer noch gesetzt, richtig?
Ja.
Allerdings ist es nicht "immer noch" gesetzt, sondern "schon wieder". 
Wegen des neuen Übertrags nämlich.

von Mike (Gast)


Lesenswert?

Hätte noch zwei Fragen: Wie ist das eigentlich beim or Befehl. Habe 
einmal 0xa5 und einmal 5a. Beide werden mit or Befehl verarbeitet. 
Ergebniss ist dann 0xff, also 255. Carry war vorher gesetzt. Da aber 
Wertebereich von 0 bis 255 geht, müsste Carry dann nach dem Ausführen 
vom Befehl 0 sein oder? Erst bei 256 müsste Carry =1 sein??!!


Zweite Frage: Stimmt das, dass man nur bei adc und sbc den wertebereich 
von -128 bis 127 hat und bei allen anderen Befehlen von 0 bis 255? Die 
Frage bezieht sich auf den V-Flag :)

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> Hätte noch zwei Fragen: Wie ist das eigentlich beim or Befehl. Habe
> einmal 0xa5 und einmal 5a. Beide werden mit or Befehl verarbeitet.
> Ergebniss ist dann 0xff, also 255. Carry war vorher gesetzt. Da aber
> Wertebereich von 0 bis 255 geht, müsste Carry dann nach dem Ausführen
> vom Befehl 0 sein oder? Erst bei 256 müsste Carry =1 sein??!!


SChau ins Datenblatt bzw. in die Befehlsbeschriebung deines Prozessors. 
Bei jedem Befehl ist akribisch vermerkt, ob und wenn ja welche Flags von 
dem Befehl berücksichtigt bzw. verändert werden.
Du wirst diese Information noch oft brauchen und wenn du sie nicht 
auswendig weißt dann musst du wissen, wo du sie finden kannst. Im 
AVR-Studio ist das besonders einfach: Du stellst den Cursor auf einen 
Befehl und drückst F1 (und kannst dann in der Hilfe auch die anderen 
Befehle finden)

>
> Zweite Frage: Stimmt das, dass man nur bei adc und sbc den wertebereich
> von -128 bis 127 hat und bei allen anderen Befehlen von 0 bis 255? Die
> Frage bezieht sich auf den V-Flag :)

Nein das stimmt nicht.
Ein Byte ist ein Byte und hat als solches 8 Bit. Ob du diese 8 Bit als 
von 0 bis 255 betrachtest (also ohne Vorzeichen) oder als von -128 bis 
+127 (also mit Vorzeichen) ist einzig und alleine eine Frage dessen, wie 
du die Bitmuster interpretieren willst.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Arithmetik8

von spess53 (Gast)


Lesenswert?

Hi

Sieh dir mal das

http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf

an.

>Hätte noch zwei Fragen: Wie ist das eigentlich beim or Befehl. Habe
>einmal 0xa5 und einmal 5a. Beide werden mit or Befehl verarbeitet.
>Ergebniss ist dann 0xff, also 255. Carry war vorher gesetzt. Da aber
>Wertebereich von 0 bis 255 geht, müsste Carry dann nach dem Ausführen
>vom Befehl 0 sein oder? Erst bei 256 müsste Carry =1 sein??!!

Bei einem 'Oder' kann kein Wert >255 entstehen. In der 
Befehlsbeschreibung  findest du, wie welche Flags gesetzt werden.

>Zweite Frage: Stimmt das, dass man nur bei adc und sbc den wertebereich
>von -128 bis 127 hat und bei allen anderen Befehlen von 0 bis 255? Die
>Frage bezieht sich auf den V-Flag :)

Nein. In Assembler gibt es nur Bytes. Daraus kann man Word, DWord ... 
machen. Ob du das als vorzeichenbehaftet betrachtest entscheidest du. 
Also $FF kann je nach Betrachtungsweise 255 oder -1 sein. Und danach 
richtet sich auch die Relevanz der Flags.

MfG Spess

von Mike (Gast)


Lesenswert?

Na gut, aber in der Klausur muss ich entscheiden, ob ich ein Flag setze 
oder nicht und soweit ich weiß sind adc und sbc die Befehle, wo ich mich 
im Bereich von -127 bis 128 aufhalte und alles was außerhalb ist, ist V 
Flag = 1

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Der Wertebereich wird nicht durch die Operation bestimmt, die V- oder
C-Flag gesetzt (oder gelöscht) hat, sondern lediglich durch die
Operation, die die Flags dann auswertet (typischerweise ist das ein
bedingter Sprung).  Erst an dieser Stelle wird also entschieden, ob
die vorangegangene Rechnung ganzzahlig (Wertebereich 0 .. 255) oder
vorzeichenbehaftet (Wertebereich -128 .. +127) interpretiert werden
soll.

von Mike (Gast)


Lesenswert?

Also hat es nichts damit zutun, wie die Falgs vor der Operation gesetzt 
waren und es hat auch nichts direkt mit dem Befehl zutun?

von Ralf (Gast)


Lesenswert?

Mal so zur bildlichen Darstellung:
(111    = jeweils 1 gemerkt: Das ist ein Flag (hier von 1 bis 9, binär 
nur 1)
  789
+ 456
 ----
 1245

von Mike (Gast)


Lesenswert?

Ok, aber was ich nicht verstehe:

z.B. habe ich eine eor Befehl. Im Instruction Handbuch steht für 
Carryflag nach dem Befehl ein "-"

Bedeutet das, dass wenn vorher ein Cflag gesetzt war, es auch nach dem 
Befehl gesetzt ist? Es gibt in dem Buch Flags, wo eine Null steht, für 
nicht gesetzt, dann gibt es noch diesen Strich "-"

z.B. eor 0xc3, 0xff

Da würde ich kein C-Flag setzen für das Ergebnis. Im Handbuch steht wie 
gesagt nur ein Strich "-" ...

von spess53 (Gast)


Lesenswert?

Hi

>Da würde ich kein C-Flag setzen für das Ergebnis. Im Handbuch steht wie
>gesagt nur ein Strich "-" ...

Es gibt vier Möglichkeiten, wie sich ein Befehl auf ein Flag auswirkt:

- Flag wird entsprechend Ergebnis gesetzt
- Flag wird gelöscht
- Flag wird gesetzt
- Flag bleibt unbeeinflusst

Ein eor ,and , or ... können kein Ergebnis haben, das das Anzeigen 
eines Übertrags erfordert. Warum sollte das Flag dann beeinflusst 
werden?

MfG Spess

von Steffen H. (avrsteffen)


Lesenswert?

Das "-" bedeutet:
Das jeweilige Flag wird durch diese Operation nicht beeinflusst.

von Mike (Gast)


Lesenswert?

Genau das meinte ich. Wenn in dem handbuch steht z.B. V=0, dann ist V 
danach = 0. wenn dort ein rechts/links Pfeil steht, wird Flag vom 
Ergebnis beeinflusst. FWenn da aber ein "-" Strich steht, bedeutet das, 
dass das Flag genau so bleibt, wie vorher, stimmts?

Weil ganz am einfach jemand geschrieben hat, dass das Flag immer neu 
gesetzt wird ... Daher wusste ich nicht genau, was damit gemeint ist. Da 
eor das Flag aber wie du schon sagst nicht beeinflusst, wird es, wenn 
nicht im handbuch anders beschrieben, nicht Null gesetzt, sondern wie 
anfangs angegeben belassen ... Außer es steht im handbuch C=0.

Hab ich das richtig interpretiert?


So nebenbei eine kleine Frage noch. Wenn ich Z=0x0210 habe und z.B. push 
zl und push zh schreibe und dann Adresse:Wert sehen möchte, welchen Wert 
haben die beiden dann? als Wert habe ich 02 und 10 stehen, aber warum?

Z=0x0210 ist ja nicht mein Wert, sondern damit schaue ich anhand einer 
tabelle, welcher Wert darin steckt, ...

von spess53 (Gast)


Lesenswert?

Hi

>So nebenbei eine kleine Frage noch. Wenn ich Z=0x0210 habe und z.B. push
>zl und push zh schreibe und dann Adresse:Wert sehen möchte, welchen Wert
>haben die beiden dann? als Wert habe ich 02 und 10 stehen, aber warum?

>Z=0x0210 ist ja nicht mein Wert, sondern damit schaue ich anhand einer
>tabelle, welcher Wert darin steckt, ...

>...und dann Adresse:Wert sehen möchte, welchen Wert
>haben die beiden dann? als Wert habe ich 02 und 10 stehen, aber warum?

Adresse:Wert gibt es nicht. Jeder 'Ladebefehl', der das Z-Register 
benutzt, hat auch ein Ziel:

   lpm         -> r0
   lpm rxy,z   -> rxy
   ld rxy,z    -> rxy

das Ziel wird also im Befehl spezifiziert.

MfG Spess

von Steffen H. (avrsteffen)


Lesenswert?

Z ist ein Pointerregister und besteht aus Z= ZH|ZL oder Z=R31|R30

Wenn steht Z=0x0210, dann hat Z auch den Wert 0x0210.

Wenn du aber eine Operation wie
ld R4, Z
oder
st Z, R4
hast, dann beschreibt der Inhalt von Z eine Adresse.

von Mike (Gast)


Lesenswert?

Also bei mir steht z.B. Z=0x0210
und mein ZH ist 0x02 und ZL ist 0x10 .... steht zumindest so ...

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.