Subtraktion auf PIC

Die Subtraktion in Assembler auf PIC-Mikrocontrollern bereitet einiges an Kopfzerbrechen:

Der SUBWF-Trick (nur 8 Bit)

Um Differenzen zweier Abtastwerte oder Timer-Werte zu bilden, muss man den vorherigen Wert verarbeiten und danach den neuen Wert (nicht die Differenz) speichern.

	movfw	tic
	subwf	TMR0,w	; w = tic-TMR0 = negative Differenz
	subwf	tic,f	; tic = tic-(tic-TMR0) = TMR0
;Jetzt in W die negative Differenz und in tic der neue TMR0-Wert

Man benötigt so kein Zwischenregister zum Festhalten des gelesenen TMR0-Wertes.

Der ADDWF-Trick (nur 8 Bit)

Wie oben, mit positiver Differenz. Wichtig für PIC12F508, der keinen Timerüberlauf-Interrupt (nicht mal ein Flag) hat.

	movfw	TMR0
	subwf	tic,w	; w = TMR0-tic = vergangene Zeit
	addwf	tic,f	; tic = tic+(TMR0-tic) = TMR0
;Jetzt in W die vergangene Zeit und in tic der neue TMR0-Wert
;Außerdem ist C bei Timerüberlauf gesetzt. Das passt für:
	skpnc
	 incf	t0h,f	;16-Bit-Erweiterung von TMR0 nachführen

In der gleichen Weise funktioniert auch der XOR-Trick zur Abfrage von Tasten und Inkrementalgebern.

Verkettung

Für 16-Bit-Zahlen muss bei Überlauf beim Low-Byte das High-Byte dekrementiert werden. Denn es fehlt ein Subtraktionsbefehl mit Übertrag, etwa subb oder sbc. Den gibt's erst bei größeren PICs.

	movfw	subtrahend
	subwf	minuend,f
	skpc			; C=1: kein(!) Überlauf
	 decf	minuend+1,f	; Übertrag als zusätzliche Subtraktion von 1
	movfw	subtrahend+1
	subwf	minuend+1,f

Bereichsprüfung

Wenn kein sublw-Befehl zur Verfügung steht, muss der zu prüfende Wert in ein Register (testvar, nicht in W) und es geht weiter wie folgt:

	movlw	minimum
	subwf	testvar,w
	bnc	error
	movlw	maximum		; hier: Maximum+1
	subwf	testvar,w
	bc	error		; auch bei Gleichheit
	;hier ist minimum < testvar ≤ maximum (vzl.)
error:	;hier: C=0: zu klein, C=1: zu groß