Der schnellste Weg, um in ASM ein bisschen umzuschalten

7

Was ist der schnellste Weg, um in MPASM ein Bit 1 für den erweiterten 14-Bit-Befehlssatz umzuschalten? (Ich arbeite mit einem PIC16F1829)

Der Code muss eigenständig sein - ich meine, er kann jederzeit aufgerufen werden, ohne den Wert des Bits in diesem Moment zu kennen.

Hauptkriterium ist hier die Geschwindigkeit : Ein Programm mit weniger Befehlszyklen ist besser. Die Anzahl der Befehlszyklen wird berechnet als die Anzahl, wenn das Bit 0 ist + die Anzahl, wenn das Bit 1 ist, geteilt durch 2.

1: Mit Toggle meine ich, dass der Code ähnlich wie pin=!pinin C sein muss


quelle
Was ist ein PIC16-Gerät? Nennen Sie es besser beim Kern, ich denke, Sie meinen den 14-Bit-Kern (nicht erweitert)?
Wouter van Ooijen
@WoutervanOoijen danke, gute Idee - es ist übrigens der verbesserte Kern für diesen Chip, aber das konnte man natürlich nicht wissen.
Interessanterweise kann 'pin =! Pin' in C stark explodieren. XC16 für PIC24 verwandelt dies in 11-12 Montageanweisungen, da die BTG-Anweisung nicht beachtet wird. (GCC-Compiler zielen auf Portabilität gegenüber Optimierung ab, daher sind Dinge wie __builtin_btg erforderlich)
Adam Lawrence,
1
@ Madmanguruman Ich meine, es muss das gleiche tun, nicht dass es so schnell sein muss :)
@CamilStaps wäre es nicht besser, meine Antwort auszuschließen, indem ich sie (nachträglich) mit einigen bearbeiteten Wörtern in der Frage ungültig mache. Nach dem derzeitigen Stand der Frage ist meine Antwort der schnellste Weg, um Ihr Ziel zu erreichen, und jemand, der spät zu dieser Frage kommt, fragt sich möglicherweise, warum Sie meine Antwort nicht akzeptiert haben. Ich bin sehr glücklich, meine Antwort zu löschen, wenn Sie es irgendwie ausschließen können.
Andy aka

Antworten:

14

Sie können Folgendes mit einem XOR versuchen:

movlw 0x01 ; move 0x01 to W register
xorwf lat, F ; XOR W with port & store result in port latch

Eine exklusive ODER-Verknüpfung behält die Werte in Bits bei, bei denen die Bits im Arbeitsregister auf Null gesetzt sind, und invertiert die Werte, bei denen sie gesetzt sind. Sie können also auch dieselbe Technik verwenden, um mehrere Bits umzuschalten.

PeterJ
quelle
2
PeterJ, kennen Sie das Problem Read-Modify_write? - Update: Camil hat die Regeln klargestellt: 14-Bit Enhanced Core ==> Verwenden Sie das LAT-Register anstelle des PORT !!!
Wouter van Ooijen
Ich denke, dies ist die kürzeste Zeit, die Sie auf Geräten erhalten, die keine BTG-Anweisung unterstützen (PIC18, PIC24 usw.)
Adam Lawrence
@WoutervanOoijen, ja guter Punkt, ich werde die Antwort aktualisieren
PeterJ
1

Ich habe mir das ausgedacht:

;                                                           Cycles if 1 | Cycles if 0
btfss    port, pin  ; skip next instruction if 1            1           | 1
goto     $+3        ; pin=0, goto PC+3                      1           | 2
bcf      port, pin  ; pin=1, clear pin and...               1           | 
goto     $+2        ;   ...proceed program                  2           |
bsf      port, pin  ; pin=0, set pin and proceed program                | 1           +
; ...                                                       ---------------------------
;                                                           5             4

Dies dauert 4 oder 5 Anweisungszyklen. Ist etwas schneller möglich?


quelle
Ich denke, PeterJs XOR ist das dickste. Aber bleiben Sie bei Ihrem Stil: Versuchen Sie, die Pin-Einstellung zu überspringen, anstatt herumzuspringen. Durch die Pin-Einstellung werden die Flags nicht geändert, sodass Sie auf diese Weise sowohl die then- als auch die else-Klausel überspringen können.
Wouter van Ooijen
@WoutervanOoijen meinst du btfss; bsf;; bcf? Dann würde das Bit unabhängig vom Zustand gelöscht. Was meinst du? :)
Wenn nicht gesetzt, dann do_set, dann do_clear, sonst do_clear. Das funktioniert auch bei mir.
Andy aka
@Andyaka dies ist ein wenn nicht_set dann do_clear sonst do_set
@CamilStaps Ich habe Ihre Interpretation von Wouters Kommentar kommentiert - ich war ein wenig verspielt, weil ich nicht glaube, dass Sie die Frage gestellt haben - ich glaube, Sie möchten, dass der "Code" ein bisschen invertiert und dann beendet oder das Bit dann invertiert wieder umkehren und dann beenden.
Andy aka
1

Was ist der schnellste Weg, um ein Bit1 in MPASM für den erweiterten 14-Bit-Befehlssatz umzuschalten? (Ich arbeite mit einem PIC16F1829)

Der Code muss eigenständig sein - ich meine, er kann jederzeit aufgerufen werden, ohne den Wert des Bits in diesem Moment zu kennen.

Hauptkriterium ist hier die Geschwindigkeit: Ein Programm mit weniger Befehlszyklen ist besser. Die Anzahl der Befehlszyklen wird berechnet als die Anzahl, wenn das Bit 0 ist + die Anzahl, wenn das Bit 1 ist, geteilt durch 2.

1: mit toggle meine ich, dass der Code ähnlich sein muss wie pin =! Pin in C.

Ich habe angenommen, dass das Bit, das Sie umschalten möchten, Teil eines Registers ist, das in den anderen Bits "egal" hat und daher Swap-Nibbles funktionieren würden. Sie haben nie gesagt, dass es so nicht funktionieren könnte, und wenn Sie so wenig Register haben, dass Sie die anderen Bits benötigen, wird ein Umschreiben des Codes oder ein MCU-Upgrade empfohlen.

Sie müssten zunächst 11110000 einrichten (jedes Muster würde dies tun, wenn bn nicht gleich bn + 4 ist), danach jedoch jedes Mal, wenn Sie eines der verwendeten Bits invertieren möchten: -

swapf f, d

Es ist eine Ein-Zyklus-Operation und benötigt keine 1 im w-Register.

Natürlich müssten Sie im Rest des Programms diese Methode zum erneuten Ändern des Bits einhalten, ABER Sie haben nicht gesagt, dass Sie dies nicht können - mit anderen Worten, BCF- oder BSF-Anweisungen sind verboten.

Ich habe über Rotationen nachgedacht, aber sie drehen sich durch Carry und dies würde wahrscheinlich das Zeug beschädigen. Ich habe seit über 20 Jahren keinen PIC-Code mehr geschrieben, daher sollte Vergebung bei der Abstimmung im Vordergrund stehen !!!

Andy aka
quelle
0

Wenn Sie eine PIN invertieren möchten, müssen Sie den Status der PIN laden, sodass Sie zuerst die Bank für PORTA auswählen müssen. Hier ist der Code in C:

// PORTAbits.RA5=~PORTAbits.RA5;
PORTA=PORTA ^ 0b00100000;

mit dem Ergebnis in ASM:

 MOVLB 0x0
 MOVF PORTA, W
 XORLW 0x20
 MOVWF PORTA
Buchstabieren
quelle
Es sieht so aus, als ob die akzeptierte Antwort um einen Zyklus schneller ist, selbst wenn der Bankschalter eingebaut ist (was nicht immer erforderlich ist, wenn Sie verfolgen, in welcher Bank Sie sich befinden). Natürlich liefert der C-Compiler nicht immer den schnellsten kompilierten Code - insbesondere die kostenlosen Compiler von Microchip generieren sehr unoptimierten Code.