2014-12-09 12 views
5

Ich möchte eine 16-Bit-Nummer durch zwei teilen. Meine Lösung für das Problem war, wie untenWie teilt man 16-Bit-Nummer durch 2 in 6502 Asm?

lda $17 ;set high byte 
    ldx $32 ;set low byte 

divide: 
    PHA   ;push A to stack   
    TXA   ;X > A 
    LSR   ;divide low byte by 2 
    TAX   ;A > X 

    PLA   ;pull A from stack 
    LSR   ;divide high byte by 2 
    BCC +  ;C=0, skip 

    PHA   ;while C=1 
    TXA   ;add $80 to the lsb 
    ADC#$80 
    TAX 
    PLA 
+ 
    +printDecimal $0400+120 

Alle PHA/PLA Tricks ist, weil mein printDecimal Makro MSB von A liest und LSB von X.

Wenn ich Alternativen online überprüfen, fand ich 4 Anweisung Alternative zu meiner bescheidenen Division Routine. Aber ich habe es nicht verstanden.

div2: 
    LDA counter_hi  ;Load the MSB 
    ASL     ;Copy the sign bit into C 
    ROR counter_hi  ;And back into the MSB 
    ROR counter_lo  ;Rotate the LSB as normal 

    LDA counter_hi 
    LDX counter_lo  
    +printDecimal $0400+40  

Wie funktioniert das?

Antwort

8

Division durch 2 (einer vorzeichenlosen Zahl) ist das Gleiche wie alle Bits um eine Position nach rechts verschoben werden. Zum Beispiel wird die Zahl 100 in binär dargestellt durch:

01100100 

Verschieben aller eine Positionen nach rechts Ausbeuten

00110010 

, die von 50.

Die ROR-Befehl bewegt sich die binäre Darstellung ist alle Positionen rechts. Das neue MSB des Bytes ist gleich dem alten Wert des Übertrag-Flags, während der neue Wert des Übertrag-Flags gleich dem alten LSB des Bytes ist.

Wenn die die 16-Bit-Zahl ohne Vorzeichen ist, genügt es, die hohe und das niedrige Byte der Zahl nach rechts zu verschieben:

LSR counter_hi 
ROR counter_lo 

LSR und ROR sowohl verschiebt ihr Argument nach rechts, aber LSR macht das MSB von counter_hi 0 und verschiebt das LSB von counter_hi in das Übertrags-Flag, während ROR das MSB von counter_lo gleich dem (alten) LSB von counter_hi macht.

Wenn die Nummer signiert ist, müssen Sie das Vorzeichenbit speichern und sicherstellen, dass das Vorzeichenbit der neuen Nummer identisch ist. Das ist es, was die ersten beiden Befehle des von Ihnen angegebenen Codes tun. Beachten Sie, dass dies funktioniert, da die Nummer in two's complement gespeichert ist.

+5

LSR = CLC + ROR – i486

+0

diese. Multiplikation und Division durch (Vielfache von) Zwei sind nichts anderes als Bitverschiebungen nach links oder rechts. 'LSR hi-byte, ROR lo-byte' erreicht Ihr 16-bit-Divisionsziel ohne viele Schleifen, Register-Swaps usw. –

+0

@ i486. Danke i486. Ich habe die Antwort bearbeitet. – Hoopje

2

Wenn ich mich richtig erinnere, verschieben die ROR und ROL die Bits in der angegebenen Richtung und das niedrigstwertige Bit (für ROR) und höchstwertig (für ROL) werden in das Carry-Flag verschoben.

Es ist ungefähr 25 Jahre her, seit ich einen 6502 gesehen habe, obwohl es mir nicht ganz klar ist, aber das ist sofort, wie ich dachte, dass es gemacht würde.

Edit: Auch in ROR und ROL wird der vorhandene Zustand des Übertrags-Flags in das kleinste/höchstwertige Bit des Akkumulators übertragen.

4

Es funktioniert wie die Kommentare im Code sagen;) In 6502 gibt es leider keine arithmetische Verschiebung rechts, die das Zeichen Bit intakt lassen würde. Also muss es emuliert werden. Dazu wird zuerst das Vorzeichenbit aus dem High-Word extrahiert. Beachten Sie, dass dies unter Verwendung des Akkumulators geschieht, so dass der ursprüngliche Wert nicht geändert wird. Das ROR wird für das High-Wort verwendet, das den 9-Bit-Wert dreht, der durch das Erweitern des Operanden mit dem Übertrags-Flag erzeugt wird. Als solches wird das Vorzeichenbit, das gegenwärtig in CF ist, in das MSB gedreht, der Rest der Bits wird nach rechts verschoben und das LSB wird in der CF enden. Dies führte zu einer unterzeichneten Abteilung. Die zweite ROR auf dem niedrigen Wort überträgt einfach das LSB von dem hohen Wort in das MSB des niedrigen Wortes und verschiebt den Rest der Bits nach rechts.

2

(Natürlich kennen Sie Verschieben nach rechts von N Bits dividiert durch 2^N, und in ähnlicher Weise nach links multipliziert mit 2 Verschiebung)

Von this reference:

setzt das Most Significant Bit (MSB) der hallo Byte counter_hi in das Carry-Register (damit das Zeichen beim Verschieben gespeichert wird - Division durch eine positive ganze Zahl (2) ändert nicht das ursprüngliche Vorzeichen unserer 16-Bit-Nummer).

ROR counter_hi verschiebt die counter_hi um 1 Bit nach rechts. Wichtig:

Der Übertrag wird in Bit 7 verschoben und das ursprüngliche Bit 0 wird in den Übertrag verschoben.

, die zwei Zwecken dient - das ursprüngliche Zeichen zu halten, und wird übertragen auch das LSB von counter_hi für den zweiten ROR

ROR counter_lo dann tut das gleiche für das Low-Byte. Das LSB des counter_hi wird nun in das MSB von counter_lo verschoben

2

Sie alle Adressierungsarten von Anweisungen nicht erinnern, aber vielleicht ist das in Ordnung:

LSR 
PHA 
TXA 
ROR 
TAX 
PLA