Forum: Compiler & IDEs Addition zweier 16 bit Werte in Assembler


von Michael Niedrat (Gast)


Lesenswert?

Hallo Forum,

ich bin langjähriger C-Programmierer und möchte mich nun etwas mit 
Inline-Assembler befassen. Ich habe auch schon den Einstieg gefunden, 
aber tue mir manchmal doch noch schwer damit, besonders mit größeren 
zusammengesetzten Operationen.

Ich möchte möglichst schnell und elegant zwei 16 bit Werte addieren in 
einem ATmega16. Die beiden 16 bit Werte stehen fest in Registern, also

R0 = Lowbyte des 16 bit Wertes 1
R1 = Highbyte des 16 bit Wertes 1

R2 = Lowbyte des 16 bit Wertes 2
R3 = Highbyte des 16 bit Wertes 2

Wie mache ich das am effektivsten in Assembler? Ich habe so meine 
Probleme mit dem Carry...

vielen Dank für alle Tips!

Michael

von Udo S. (urschmitt)


Lesenswert?

Du addierst die beiden Low Bytes.
Kommt es zu einem Überlauf ist das Carry automatisch gesetzt.
Jetzt addierst du mit Carry (dazu gibt es oft einen eigenen Befehl) die 
beiden High Bytes.
Wo ist das Problem?
Interessant wird es dann wenn du eine Division implementierst :-)

von Michael Niedrat (Gast)


Lesenswert?

Hallo Udo,

vielen Dank für deine Antwort! Das kann ich nachvollziehen. Aber was 
passiert dann genau bei einem Überlauf des High-Bytes?

Beispiel:

Der erste 16-bit Wert sei 65500, der zweite 16-bit Wert sei 100. Ich 
addiere beide nach Deinem Schema oben. Was steht dann danach als 
Ergebnis ?

Puhh- ich merke schon dass man mit C einfach weit weg ist von den 
Grundlagen, dort muss man sich (fast) keine Sorgen um sowas machen...

Michael

von Daniel V. (danvet)


Lesenswert?

Es passiert das gleiche wie bei den LOW-Bytes. Das Carry wird gesetzt 
:-)
Teste auf "Carry", dann hast du einen Überlaufdetektor.

In C hättest du aber auch einen Überlauf!

von avr (Gast)


Lesenswert?

avr:

add r0,r2
adc r1,r3

von Martin (Gast)


Lesenswert?

Kann man  den C Compiler  Assembler-Code  ausgeben lassen?
So kann man leicht sehen  wie  es der Compiler macht.

von Michael Niedrat (Gast)


Lesenswert?

Ok, das ist klar...

Aber was ist das Ergebnis? Steht dann also nach der Addition quasi das 
was nicht reingepasst hat als "Rest" da ?

Beispiel:

65500 + 100 = 65600  --> das passt aber nicht in einen 16-bit Wert rein

Bei 65535 erfolgt der Überlauf. Es wurden "65" zu viel addiert. Steht 
dann nach der Addition also "64" als Ergebnis (eins weniger wegen der 
NUll)?

Ich bin mir immer noch so unsicher mit den binären Zahlen...

Michael

von Dominik S. (dasd)


Lesenswert?

Martin schrieb:
> Kann man  den C Compiler  Assembler-Code  ausgeben lassen?
> So kann man leicht sehen  wie  es der Compiler macht.

Klar.
Der Compile erzeugt aus dem C-Code erstmal ein Assembler-Listing.
Eine Datei mit Namen *.lst, im Projektordner.

Michael Niedrat schrieb:
> Bei 65535 erfolgt der Überlauf. Es wurden "65" zu viel addiert. Steht
> dann nach der Addition also "64" als Ergebnis (eins weniger wegen der
> NUll)?

Nein, im Register steht dann 0xFF und es gibt ein Carry-Bit.
Den Rest kannst du nicht auffangen.

von Daniel V. (danvet)


Lesenswert?

Michael Niedrat schrieb:
>
> Ich bin mir immer noch so unsicher mit den binären Zahlen...
>
> Michael

Und du bist langjähriger C Programmierer? Du erhälst das gleiche 
Ergebnis wie in C. (wie du geschrieben hast: 64 + Carry)

von Daniel V. (danvet)


Lesenswert?

Dominik S. schrieb:

>
> Nein, im Register steht dann 0xFF und es gibt ein Carry-Bit.
> Den Rest kannst du nicht auffangen.

Hä??

von Michael Niedrat (Gast)


Lesenswert?

Danke, Daniel!

Offensichtlich stiftet diese Frage ja schon Verwirrung... ich hatte 
jetzt zwei unterschiedliche Antworten :-)

Soll ich noch einen draufsetzen? Also...

Wie ist das bei Einer-Komplement und Zweierkomplement ?

Es interessiert mich wirklich.

Vielen Dank an alle!!

Michael

von Dominik S. (dasd)


Lesenswert?

Dominik S. schrieb:
> Nein, im Register steht dann 0xFF und es gibt ein Carry-Bit.
>
> Den Rest kannst du nicht auffangen.

Oh je ^^ das natürlich ganz schnell wieder vergessen - weiß Gott wie da 
grad drauf kam ^^

So wär's natürlich nur wenn man eine Arithmetik mit Sättigung 
implementieren 
will(http://www.mikrocontroller.net/articles/AVR_Arithmetik/Saturierung)

von Daniel V. (danvet)


Lesenswert?

Dominik S. schrieb:
> Dominik S. schrieb:
>> Nein, im Register steht dann 0xFF und es gibt ein Carry-Bit.
>>
>> Den Rest kannst du nicht auffangen.
>
> Oh je ^^ das natürlich ganz schnell wieder vergessen - weiß Gott wie da
> grad drauf kam ^^
>
> So wär's natürlich nur wenn man eine Arithmetik mit Sättigung
> implementieren
> will(http://www.mikrocontroller.net/articles/AVR_Arithmetik/Saturierung)

Na das sieht ja mal ganz gut aus :-)

von Daniel V. (danvet)


Lesenswert?


von Michael Niedrat (Gast)


Lesenswert?

Danke für den Link, das sieht sehr passend aus. Hab ich irgendwie nicht 
gefunden!

Nochmals Danke an alle für die vielen tollen Antworten! Und alles in 
Rekordzeit!

Michael

von Ralf G. (ralg)


Lesenswert?

Udo Schmitt schrieb:
> Du addierst die beiden Low Bytes.
> Kommt es zu einem Überlauf ist das Carry automatisch gesetzt.
> Jetzt addierst du mit Carry (dazu gibt es oft einen eigenen Befehl) die
> beiden High Bytes.
> Wo ist das Problem?

@Michael
Du mußt dir angewöhnen, Gemeinsamkeiten zwischen Zahlensystemen zu 
erkennen!

Mal dein Beispiel aufgegriffen:

in r0 -> Einerstelle ('low-Byte') der ersten Dezimalzahl
in r1 -> Zehnerstelle ('high-Byte') der ersten Dezimalzahl
in r2 -> Einerstelle ('low-Byte') der zweiten Dezimalzahl
in r3 -> Zehnerstelle ('high-Byte') der zweiten Dezimalzahl

Wie machst du jetzt eine schriftliche Addition (später Multiplikation 
und Division (auf Bit-Ebene))? -> ganz einfach, oder?

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.