Forum: Mikrocontroller und Digitale Elektronik Assembler t2313 32bit 2er kompl.


von Rudi D. (rulixa)


Lesenswert?

Zahl In RR[4:7] in 2er Kompl. wandeln.

Geht es einfacher?

clr   A
com RR4       :setzt carry
com RR5
com RR6
com RR7       ; C=1 wird gleich als +1 verwendet
adc RR4,A
adc RR5,A
adc RR6,A
adc RR7,A      ; carry wird verworfen

von spess53 (Gast)


Lesenswert?

Hi

>Geht es einfacher?

Einem Befehl kann man sparen:

[avrasm}
   com r16
   com r17
   com r18
   com r19
   subi r16,Low(-1)
   sbci r17,byte2(-1)
   sbci r18,byte3(-1)
   sbci r19,byte4(-1)
[/avrasm}

MfG Spess

von Rudi D. (rulixa)


Lesenswert?

Verstehe es nicht ganz. subi und sbci geht immediate ist klar, darum 
kein clr A
o.k. aber dann? wo ist der byte Zähler
Danke Rudi

: Bearbeitet durch User
von Rudi D. (rulixa)


Lesenswert?

Ich brauche doch etwas Nachhilfe
 In der AVR-Hilfe unter expressions findet sich z.B.

byte2(expression) was ident ist mit high(expression), dass dies das 
2.Byte eines Ausdruckes liefert. Gut!

Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann
byte2 oder byte3 oder byte4(-1) zurück?

Wenn es 0 ist, so verstehe ich die Antwort von spess53.

In meiner nicht so großen Erfahrung würde ich aber dann schreiben, wenn 
es richtig ist:
[avrasm}
   com r16
   com r17
   com r18
   com r19
   subi r16,(-1)   ; ident mit add 1
   sbci r17,0      ; wenn Übertrag, dann nur carry addieren
   sbci r18,0
   sbci r19,0
[/avrasm}

Aber ist das richtig?
Bitte um Nachhilfe

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann
>byte2 oder byte3 oder byte4(-1) zurück?

Assembler Hilfe:

BYTE2(expression) is the same function as HIGH
BYTE3(expression) returns the third byte of an expression
BYTE4(expression) returns the fourth byte of an expression

In diesem Fall ist expression = -1 oder $FFFFFFFF

>Wenn es 0 ist, so verstehe ich die Antwort von spess53.

Der Befehl com ist das Einerkomplement (oder Negation) und mit
Rd ← $FF - Rd definiert. Das Zweierkomlement (neg) mit Rd ← $00 - Rd. 
Also ist neg(Wert) = com(Wert)+1. Da es keine ADDI/ADCI-Befehle gibt, 
werden die in dem Fall durch subi/sbci -1 ersetzt.

Funktioniert bei mir seit Jahren. Teste es einfach im Simulator.

MfG Spess

von (prx) A. K. (prx)


Lesenswert?

Rudi D. schrieb:
> Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann
> byte2 oder byte3 oder byte4(-1) zurück?

Das bezieht sich auf Konstanten oder konstante berechnete Ausdrücke im 
Assembler, nicht auf Werte in Registern. Solche Ausdrücke werden vom 
Assembler in 32 Bits gerechnet.

: Bearbeitet durch User
von Rudi D. (rulixa)


Lesenswert?

A. K. schrieb:
> Rudi D. schrieb:
>> Aber der t2313 hat ja nur 1 Byte Weite. Also was liefert dann
>> byte2 oder byte3 oder byte4(-1) zurück?
>
> Das bezieht sich auf Konstanten oder konstante berechnete Ausdrücke im
> Assembler, nicht auf Werte in Registern. Solche Ausdrücke werden vom
> Assembler in 32 Bits gerechnet.

Das hat mir gefehlt. Wo steht das im AVR Studio, habs nie gefunden.

von Rudi D. (rulixa)


Lesenswert?

spess53 schrieb:
> Der Befehl com ist das Einerkomplement (oder Negation) und mit
> Rd ← $FF - Rd definiert. Das Zweierkomlement (neg) mit Rd ← $00 - Rd.
> Also ist neg(Wert) = com(Wert)+1. Da es keine ADDI/ADCI-Befehle gibt,
> werden die in dem Fall durch subi/sbci -1 ersetzt.

Das hab ich ja schon geschriebn, ist ja klar.

Aber sollte es nicht heißen:

   subi r16,Low(-1)
   sbci r17,byte2(0)
   sbci r18,byte3(0)
   sbci r19,byte4(0)

Es soll ja nur das ev. Carry addiert werden und nicht
r18 = r18 - ffh -C

Wo steh ich auf der Leitung?

von (prx) A. K. (prx)


Lesenswert?

Rudi D. schrieb:
> Wo steh ich auf der Leitung?

-1 = 0xFFFFFFFF
Bei dir: 0x000000FF.

Negation: B = Invertiere(A) + 1
Oder:     B = Invertiere(A) - -1
Und zwar in 32 Bits Breite.

aber wenn dir das zu kompliziert ist:
  clr  r20
  clr  r21
  movw r22, r20
  sub  r20, r16
  sbc  r21, r17
  sbc  r22, r18
  sbc  r23, r19
Ergebnis in R20-23

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Es soll ja nur das ev. Carry addiert werden und nicht
>r18 = r18 - ffh -C

Als 32-Bit-Zahl ist aber -1 = $FFFFFFFF und nicht nur $000000FF-

MfG Spess

von Rudi D. (rulixa)


Lesenswert?

spess53 schrieb:
> [avrasm}
>    com r16
>    com r17
>    com r18
>    com r19
>    subi r16,Low(-1)
>    sbci r17,byte2(-1)
>    sbci r18,byte3(-1)
>    sbci r19,byte4(-1)
> [/avrasm}

spess, das kann IMHO nicht richtig sein.

Um vom  1er Komplement, zum 2er Komplement zu kommen, ist ein einziges 
Mal 1 zu addieren und nicht 4 x

Kann aber auch sein, dass ich diese Schreibweise nicht verstehe.

von Peter D. (peda)


Lesenswert?

Der AVR-GCC meint dazu:
1
  38:  50 95         com  r21
2
  3a:  40 95         com  r20
3
  3c:  30 95         com  r19
4
  3e:  21 95         neg  r18
5
  40:  3f 4f         sbci  r19, 0xFF  ; 255
6
  42:  4f 4f         sbci  r20, 0xFF  ; 255
7
  44:  5f 4f         sbci  r21, 0xFF  ; 255
8
  return -x;

von Karl H. (kbuchegg)


Lesenswert?

Rudi D. schrieb:
> spess53 schrieb:
>> [avrasm}
>>    com r16
>>    com r17
>>    com r18
>>    com r19
>>    subi r16,Low(-1)
>>    sbci r17,byte2(-1)
>>    sbci r18,byte3(-1)
>>    sbci r19,byte4(-1)
>> [/avrasm}
>
> spess, das kann IMHO nicht richtig sein.
>
> Um vom  1er Komplement, zum 2er Komplement zu kommen, ist ein einziges
> Mal 1 zu addieren und nicht 4 x

Du addierst aber nicht +1, sondern du subtrahierst -1

Arithmetisch kommt das aufs gleiche raus.
Nur: Wenn du -1 subtrahierst, dann musst du auch wirklich -1 
subtrahieren. Und das in allen 4 Bytes der 32 Bit Zahl! Denn es kann ja 
einen Übertrag von einem Byte ins nächste geben.

Dezimal: 99 + 1 ist ja auch 100 und du hast einen Übertrag von der 2.ten 
zur 3.ten Stelle. 999999 + 1. Hier wimmelt es nur so von Überträgen von 
einer Stelle zur nächsten. Es reicht nicht, einfach nur in der 
Einerstelle die 1 zu addieren. 999999 + 1 ergibt eben nicht 999990 
sondern der Übertrag wandert die Ziffern nach vorne.

: Bearbeitet durch User
von Rudi D. (rulixa)


Lesenswert?

Darum hab ich ja in meiner 9 Lines Lösung 1addiert und 3x mögliche 
carries berücksichtigt.
GCC braucht nur 7 Befehle.
Danke auch peda, jetzt hab ich's.
Lg

: Bearbeitet durch User
von Rudi D. (rulixa)


Lesenswert?

Peter Dannegger schrieb:
> Der AVR-GCC meint dazu:
>
1
>   38:  50 95         com  r21
2
>   3a:  40 95         com  r20
3
>   3c:  30 95         com  r19
4
>   3e:  21 95         neg  r18
5
>   40:  3f 4f         sbci  r19, 0xFF  ; 255
6
>   42:  4f 4f         sbci  r20, 0xFF  ; 255
7
>   44:  5f 4f         sbci  r21, 0xFF  ; 255
8
>   return -x;
9
>

Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen 
lassen oder wer kann sonst so eine optimale Lösung erfinden?

von Cyblord -. (cyblord)


Lesenswert?

Rudi D. schrieb:
> Peter Dannegger schrieb:
>> Der AVR-GCC meint dazu:
>>
1
>>   38:  50 95         com  r21
2
>>   3a:  40 95         com  r20
3
>>   3c:  30 95         com  r19
4
>>   3e:  21 95         neg  r18
5
>>   40:  3f 4f         sbci  r19, 0xFF  ; 255
6
>>   42:  4f 4f         sbci  r20, 0xFF  ; 255
7
>>   44:  5f 4f         sbci  r21, 0xFF  ; 255
8
>>   return -x;
9
>>
>
> Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen
> lassen oder wer kann sonst so eine optimale Lösung erfinden?

Der GCC optimiert halt sehr gut. Darum muss ich auch immer schmunzeln 
wenn irgendwelche ASM-Gurus ankommen und was von Performance und 
Codegröße schwadronieren, wenn es mal wieder gegen C geht. Meist 
verliert sogar der fortgeschrittene ASM Programmierer locker gegen den 
GCC Optimierer.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rudi D. schrieb:
> Peter Dannegger schrieb:
>> Der AVR-GCC meint dazu:
>>
1
>>   38:  50 95         com  r21
2
>>   3a:  40 95         com  r20
3
>>   3c:  30 95         com  r19
4
>>   3e:  21 95         neg  r18
5
>>   40:  3f 4f         sbci  r19, 0xFF  ; 255
6
>>   42:  4f 4f         sbci  r20, 0xFF  ; 255
7
>>   44:  5f 4f         sbci  r21, 0xFF  ; 255
8
>>   return -x;
9
>>
>
> Ich habe eine Frage: hat sich das der Programmierer von GCC einfallen
> lassen oder wer kann sonst so eine optimale Lösung erfinden?

In diesem Falls: Ja.  Es ist eine "fest" vorgegebene Sequenz, die 
ausgegeben wird, wenn:  Ein 32-Bit int zu negieren ist und Ein- und 
Ausgaberegister übereinstimmen und es sich dabei um obere Register 
handelt.

Falls es keine oberen Register sind, so wird 1 Instruktion mehr 
ausgegeben:
 
1
  com r17
2
  com r16
3
  com r15
4
  com r14
5
  adc r14,__zero_reg__
6
  adc r15,__zero_reg__
7
  adc r16,__zero_reg__
8
  adc r17,__zero_reg__
 
Negation eines 16-Bit int ist übrigens immer mit 3 Instruktionen 
machbar, auch in den unteren Registern:
 
1
  neg r15
2
  neg r14
3
  sbc r15,__zero_reg__

von Rudi D. (rulixa)


Lesenswert?

Johann L. schrieb:
> Falls es keine oberen Register sind, so wird 1 Instruktion mehr
> ausgegeben:
>    com r17
>   com r16
>   com r15
>   com r14
>   adc r14,__zero_reg__
>   adc r15,__zero_reg__
>   adc r16,__zero_reg__
>   adc r17,__zero_reg__

Das ist ja fast ident mit der Frage im 1. Beitrag von mir.

Aber wie wird "__zero_reg__" dann übersetzt, da es für die unteren 
Register ja kein immediate gibt. Darum hab ich ja "clr A" dazugenommen.

Bin ja nur gelegentlich als Hobby in Assembler unterwegs. DDS und so
Projekte auf elektronik-labor.de zu lesen.

von Peter D. (peda)


Lesenswert?

Rudi D. schrieb:
> hat sich das der Programmierer von GCC einfallen
> lassen oder wer kann sonst so eine optimale Lösung erfinden?


Es gibt nicht "den" GCC-Entwickler.
Einen Compiler baut nie jemand allein in seinem stillen Kämmerlein, 
sondern daran können 10.000 und mehr Leute beteiligt sein.
Das Wissen vieler ist nunmal größer, als das eines einzelnen.

Ich war auch schwer enttäuscht, als ich meine 16Bit-Mul/Div für den 8051 
entwickelt hatte und dann mal den Keil C51 reassembliert habe. Dessen 
Code war halb so groß, dafür doppelt so schnell. Auch hatte ich 
haufenweise Push/Pop-Orgien in meinen Assemblerprogrammen, der C51 hat 
das mit Registern für Argumente und Overlay für Variablen viel 
effektiver gelöst. Von Assembler nach C umgeschriebene Programmer wurden 
daher kleiner und schneller.
Und der Herr Keil wird auch nicht alles allein gemacht haben.

von Rudi D. (rulixa)


Lesenswert?

Peter Dannegger schrieb:
> Es gibt nicht "den" GCC-Entwickler.

Allen vielen Dank.
Ich denke das Thema ist erschöpfend abgehandelt worden.

LG Rudi

von Rudi D. (rulixa)


Lesenswert?

Rudi D. schrieb:
> Aber wie wird "__zero_reg__" dann übersetzt, da es für die unteren
> Register ja kein immediate gibt. Darum hab ich ja "clr A" dazugenommen.

Nachtrag:
Dieses Register, s.o. bezieht sich auf den GCC Inline Assembler und ist 
R1 lt. GCCdoc. Es wird immer auf NULL gehalten. Näheres 
https://gcc.gnu.org/wiki/avr-gcc?action=fullsearch&context=180&value=__zero_&fullsearch=Text
Es gilt nicht für den Assembler von AVRStudio4. o.k.

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.