Hossa
Der Befehl SBC macht im Prinzip Folgendes:
SBC dest, soruce dest= dest - source - !carry
bzw. bei 3 Operanden:
SBC dest, op1, op2 dest= op1 - op2 - !carry
In jedem Fall wird jedoch das negierte(!) Carry-Flag subtrahiert. Ein Unterlauf wird also dadurch angezeigt, dass das Carry-Flag nach der Subtraktion gelöscht ist. Daher musst du vor Beginn einer Subtraktion sicherstellen, dass das Carry-Flag gesetzt ist (SEC).
Die Assembler-Befehle bzw. der Maschinen-Code ist nicht die unterste Befehlsebene einer CPU. Sie sind eigentlich nur aus Kompatibilitätsgründen vorhanden. Auf unterster Ebene repräsentieren alle CPU-Befehle eine Gruppe von sog. Microcode-Befehlen. Dieser Microcode kann bei vielen Prozessoren sogar geändert werden, um kleinere Fehler zu korrigieren. Das BIOS eines PC lädt z.B. den neuen Microcode stets während des POST in den Prozessor.
Warum das negierte Carry-Flag subtrahiert wird, ist klar, wenn man sich überlegt, wie eine Subtraktion auf Microcode-Ebene abläuft:
dest= op1 - op2 - !carry
Zur Subtraktion benötigen wir das Zweierkomplement von op2. Dazu werden alle Bits invertiert und es wird eine 1 addiert:
dest= op1 + ( !op2 + 1 ) - !carry
Ist das Carry-Bit gleich 0, wird am Ende noch eine 1 abgezogen. Ist das Carry-Bit gleich 1, wird nichts mehr abgezogen
-
Fall: carry=1 => dest= op1 + !op2 + 1
-
Fall: carry=0 => dest= op1 + !op2
Und jetzt wird klar, wie SBC auf Microcode-Ebene funktioniert:
SBC dest, op1, op2 ADC dest, op1, !op2
Mit anderen Worten, die Bits des letzten Operanden werden invertiert und dann einfach ein ADC durchgeführt…
Viele Grüße
Hase