2

これはアセンブリ言語の問題です。ユーザー入力を文字列として受け入れ、それを整数に変換する方法をすでに理解しました

現在の合計に10を掛け(3ずつシフトし、左に1位置シフトしてから、2つの結果を足し合わせます)、文字列から新しい数字を追加します(48を引くことですでに数値に変換されています)

オーバーフローが発生するまではこれで問題ありませんが、2つのレジスタに収まるように数値を分割するにはどうすればよいでしょうか。分割またはビットシフトする必要がありますか?詳しく説明してください!

4

2 に答える 2

1

このためには、倍幅の演算、つまりシフトと加算を合成する必要があります。

シフトでは、両方の半分を別々にシフトする以外に、こぼれたトップビットを下半分から上半分に取り込む必要があります。そのためには、必要に応じて下半分を右にシフトし、ビット単位ORまたは加算を使用して上半分に入れます。

擬似コード(論理シフトを使用):

result_low = (orig_low << n)
result_high = (orig_high << n) | (orig low >> (32 - n))

さらに、下半分を処理してから、元のオペランドの1つよりも小さいかどうかを確認します。そうである場合、それはオーバーフローが発生したことを意味し、加数の上位半分と上位半分にキャリーを追加する必要があります。

result_low = op1_low + op2_low
result_high = op1_high + op2_high + ((result_low < op1_low) ? 1 : 0)

可能なasm実装:

    la $t2, buff            ; pointer to string
    li $t0, 0               ; low
    li $t1, 0               ; high
loop:
    lb $t3, ($t2)           ; load next byte
    beq $t3, $zero, done    ; end of string?
    addi $t3, $t3, -48      ; convert from ascii
                            ; t4,5 = t0,1 << 1
    srl $t6, $t0, 31        ; t6 is used for the spilled bit
    sll $t4, $t0, 1         ; shift low half
    sll $t5, $t1, 1         ; shift high half
    or $t5, $t5, $t6        ; put in the spilled bit
                            ; t0,1 <<= 3
    srl $t6, $t0, 29        ; the 3 spilled bits
    sll $t0, $t0, 3         ; shift low half
    sll $t1, $t1, 3         ; shift high half
    or $t1, $t1, $t6        ; put in the spilled bits
                            ; t0,1 += t4,5
    addu $t0, $t0, $t4      ; add low halves
    addu $t1, $t1, $t5      ; add high halves
    sltu $t6, $t0, $t4      ; t6 = (t0 < t4), that is the carry
    addu $t1, $t1, $t6      ; add the carry if any
                            ; ok t0,1 has been multiplied by 10
    addu $t0, $t0, $t3      ; just add the digit now
    sltu $t6, $t0, $t3      ; the carry
    addu $t1, $t1, $t6      ; add the carry if any

    addiu $t2, $t2, 1       ; increment pointer
    b loop                  ; and continue
done:

もちろん、シフトの代わりに乗算を直接使用することもできます。

于 2012-12-10T01:42:07.013 に答える
0

番号はビットシフトされます。wikiに記載されている乗算シーケンスを参照して、LOレジスタとHIレジスタがどのように入力されるかを知ることができます。

LO = (($s * $t) << 32) >> 32;
HI = ($s * $t) >> 32;

en.m.wikipedia.org/wiki/MIPS_architecture#section_6

于 2012-12-10T01:28:38.007 に答える