5

16ビットの数値を2で割りたいです。問題に対する私の解決策は以下の通りでした

    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

すべてのPHA/PLAトリックは、私のprintDecimalマクロが A から MSB を読み取り、X から LSB を読み取るためです。

オンラインで代替案を確認したところ、私のささやかな除算ルーチンに代わる命令が 4 つ見つかりました。しかし、私は理解していませんでした。

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    

これはどのように機能しますか?

4

5 に答える 5

9

(符号なし数の) 2 による除算は、すべてのビットを 1 桁右にシフトすることと同じです。たとえば、数値 100 は次のように 2 進数で表されます。

01100100

すべての位置を 1 つ右に移動すると、

00110010

これは 50 の 2 進数表現です。

ROR コマンドは、すべての位置を右に移動します。バイトの新しい MSB はキャリー フラグの古い値に等しくなり、キャリー フラグの新しい値はバイトの古い LSB に等しくなります。

16 ビットの数値が符号なしの場合、数値の上位バイトと下位バイトを右にシフトするだけで十分です。

LSR counter_hi
ROR counter_lo

LSR と ROR はどちらも引数を右にシフトしますが、LSR は counter_hi の MSB を 0 にし、counter_hi の LSB をキャリー フラグにシフトしますが、ROR は counter_lo の MSB を counter_hi の (古い) LSB に等しくします。

数値が符号付きの場合は、符号ビットを保存し、新しい数値の符号ビットが同じであることを確認する必要があります。それが、引用したコードの最初の 2 つのコマンドが行うことです。数値は2 の補数で格納されるため、これが機能することに注意してください。

于 2014-12-09T15:32:48.710 に答える
4

コード内のコメントにあるように動作します ;) 6502 では、残念ながら算術右シフトがなく、符号ビットがそのまま残ります。したがって、エミュレートする必要があります。このために、最初に符号ビットが上位ワードから抽出されます。これはアキュムレータを使用して行われるため、元の値は変更されないことに注意してください。はROR上位ワードで使用され、オペランドをキャリー フラグで拡張して作成された 9 ビット値をローテーションします。そのため、現在 CF にある符号ビットは MSB にローテーションされ、残りのビットは右にシフトされ、LSB は CF になります。これにより、署名された分割が達成されました。下位ワードの 2 番目RORは、LSB を上位ワードから下位ワードの MSB に単純に転送し、残りのビットを右にシフトします。

于 2014-12-09T15:24:51.923 に答える
2

(明らかに、N ビットだけ右にシフトすると 2^N で除算され、同様に左にシフトすると 2 倍になります)

この参照から:

ASLhi バイトの最上位ビット (MSB) をcounter_hiキャリー レジスタに入れます (これにより、シフト時に符号が記憶されます。正の整数 (2) による除算は、16 ビット数の元の符号を変更しません)。

ROR counter_hicounter_hiを右に 1 ビットシフトします。重要:

キャリーはビット 7 にシフトインされ、元のビット 0 はキャリーにシフトインされます。

これには 2 つの目的があります。元の符号を保持しcounter_hi、2 番目の LSB を転送します。ROR

ROR counter_lo次に、下位バイトに対して同じことを行います。の LSB がcounter_hiMSB にシフトされます。counter_lo

于 2014-12-09T15:40:25.400 に答える
1

私の記憶が正しければ、ROR と ROL は指定された方向にビットをシフトし、最下位ビット (ROR の場合) と最上位ビット (ROL の場合) がキャリー フラグに移動されます。

私が 6502 を見始めてから約 25 年が経ちました。

編集: また、ROR および ROL では、キャリー フラグの既存の状態がアキュムレータの最下位/最上位ビットに転送されます。

于 2014-12-09T15:19:57.760 に答える