Bisschen Assembler

OP Persönliche Seite #326848
Lesenswert?

Hi Leute. Ich versuche gerade folgendes schneller zu machen.

Es ist in einer Interrupt Routine und soll folgendes Bewirken:
Sagen wir es gibt den CNT_PORT. Ein Port, wo an den untersten 4 Bits
ein 4/16 Decoder hängt(74HCT154). Ich möchte jetzt den Zähler immer von
0-15 durchzählen ohne den Rest vom Port zu verändern.
Folgendes habe ich mir dabei ausgedacht:

1
  cli
2
    
3
  in temp1, CNT_PORT  //Aktuellen Counterport in temp1
4
  mov temp2, temp1  //Sicherungskopie nach temp2
5

6
  inc temp1    //Um 1 erhöhen
7
  andi temp1, 0b00001111  //untersten 4 Bits bleiben über
8
  
9
  andi temp2, 0b11110000  //untersten 4 Bits löschen
10
  or temp2, temp1    //Die untersten 4 Bits aus temp1
11

12
  out CNT_PORT temp1  //Alles wieder ausgeben
13

14
  sei

Ausgenommen der Register-Sicherungsroutinen.

Habt ihr nen Vorschlag wie ich das beschleunigen könnte?
OP Persönliche Seite #326852
Lesenswert?

Nicht schlecht die Idee. So habe ich einen Hardwaremäßigen Overflow.
Aber das is nix, da ich alles schon verdrahtet habe.

@Hannes: Ah, war mir nicht sicher wegen cli und sei. Ist ja
aufjedenfall nötig. Nicht dass ein anderer Interrupt den PORT
zwischendurch noch ändert, während ich da am rumoperieren bin.

Ja sicherung habe ich drin
1
  push temp1      //Temp1 Sichern
2
  push temp2      //Temp2 Sichern
3
  in sreg_save, SREG    //SREG Sichern
4
.......
5

6
  out SREG, sreg_save    //SREG wiederherstellen
7
  pop temp2      //Temp2 wiederherstellen
8
  pop temp1      //Temp1 wiederherstellen
Gast #326853
Lesenswert?

Du könntest den Wert in CNT_PORT in zwei separaten Registern speichern.
Eines der Register ist der Zähler bis 15 und das andere enthält die
obersten 4 Bits.

  exor r31, r30
  inc  r30
  andi r30, 0x0F
  or   r31, r30
  out  CNT_PORT, r31


In r30 der Zähler, in r31 die obersten 4 Bits, macht 2 Taktzyklen
weniger, dafür 2 Register mehr verbraucht.

oder

  inc  r30
  brsh @1
  subi r30, 0x10
@@1:
  out  CNT_PORT, r30

Hier wird in r30 beides gespeichert, sowohl der Zähler und die obersten
4 Bits. Sollte nun der Zähler bei 16=0x10 überlaufen so wird das
Half-Carry-Flag gesetzt und wir müssen einfach 0x10 abziehen.
Macht dann 4 Taktzyklen und 1 Register.

Gruß hagen
OP Persönliche Seite #326854
Lesenswert?

Hmm....

Wie ist denn folgendes?
1
  in temp1, CNT_PORT //(1)
2
  swap temp1 //(1)
3
  subi temp1, -0x10 //(1)
4
  swap temp1 //(1)
5
  out CNT_PORT //(1)

Macht 5 Takte. 1Register Hihi.

Frage: Ist
subi temp1, -0x10
das equivalent zu
addi temp1, 0x10

Ich meine das so in Erinnerung zu haben. Man subtrahiert ja mit einem
negativen Wert, um zu addieren, oder?
OP Persönliche Seite #326859
Lesenswert?

Hallo xyz:

Das Problem ist, dass der AVR kein Befehl hat, um ein Immediate zu
addieren (Oder ich habe ihn schlicht übersehen). Man kann nur 2
Register addieren.

meinermeinungnach sollte aber zum Beispiel
ADDI reg, 0x01
das gleiche sein wie
SUBI reg, -0x01

bsp:

  0b00000000    steht im Register
  0b11111111    soll abgezogen werden (entspricht -0x01)

  0b00000000    Registerwert
  0b00000000    Komplement von -0x01
  ----------    addieren
  0b00000001    Kein Overflow, 1 addieren


So seh ich das.
Gast #326860
Lesenswert?

Hi

Für vorzeichenlose 8-Bit Zahlen
enspricht subi reg,-1  "addi" reg,1.

Wenn du ein Doppelregister frei hast kannst du auch adiw/sbiw
benutzen und nur das Low-Byte verwenden.Geht aber nur bis max.
+/-63.

Mfg HG

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren