前提・実現したいこと
アセンブリ言語でmult命令を使った際、上位32bitはHIレジスタに、下位32bitはLOレジスタに入ると教わったのですが、HIレジスタまで使う数が計算結果となった場合、どのようにしてHIレジスタとLOレジスタ内の値を繋ぎ合わせ値を出力すれば良いのでしょうか?
例えばですが、キーボード入力をxとして100*xを計算し表示するというプログラムはこんな感じでいけると思いますが、これだとLOレジスタ内ですむ計算しかできません。
どのようにすればHIレジスタまで使う計算結果も出力できるのでしょうか?
CPUはMIPS、処理系はSPIMです。バージョンは申し訳ないですが、分かりません
よろしくお願いします。
.data newln: .asciiz "\n" .text .globl main main: addi $sp, $sp, -4 sw $ra, 0($sp) move $t0, $zero # t0を0に初期化 li $v0, 5 syscall # 数を聞き、読み取る。これをxとした li $t1, 100 # t1に100を入れる mult $t1, $v0 # 100 * x mflo $t0 # LOレジスタからt0に値を持ってくる move $a0, $t0 li $v0, 1 #値の出力 syscall la $a0, newln # 以下改行命令 li $v0, 4 syscall lw $ra, 0($sp) # 戻り先アドレスの復元 addi $sp, $sp, 4 # スタック領域の開放 jr $ra # プログラムの終了
CPUはMIPSで、処理系はMARSですか?
お手数ですが、まずはその情報をご記載ください。
CPUはMIPSで、SPIMですね。
あ、お手数ですが、質問文にご記載ください。バージョンなども分かればお願いします。
書きました。バージョンは申し訳ないですが、大学から用意された環境で行っているのでいまいちよく分かりません。確認方法なども調べたのですが、調べ方が悪いのかわからなかったので、よろしければ教えて欲しいです。
SPIM(実行環境)であれば、対象としているCPUの種別はR2000かR3000のはずです。最新のQtSpimかそれより前のものか。QtSpimなら、ウィンドウメニューの「Help」からバージョン確認できますね。
ubuntuにaptで入れただけですが、
$ spim
SPIM Version 8.0 of January 8, 2010
Copyright 1990-2010, James R. Larus.
All Rights Reserved.
...
お使いのものと同じか分かりませんが、こんな感じに出るみたいです。
この表示だと8.0みたいですね。
@質問者さん
SPIMを使っているマシンがWindowsなのかmacなのかUN*Xなのかでもヒントになると思います。
https://ja.wikipedia.org/wiki/SPIM
参考:
ちなみにWindows版のQtSpimのバージョン情報を覗くと、
Version 9.1.21 of January 17,2020
SPIM is a simulator of the MIPS R3000 processor..
Copyright(c) 1990-2015, James R. Larus
...省略
と出ました。R3000のみサポート、なのだと思います。
とりあえず、R2000でも動くSPIMで、0~255までの数字を入力してもらってシステムコール4(文字列出力)だけで入力された整数を出力するコードを適当に書いてみました。ご参考までに。
.data
newln: .asciiz "\n"
result: .space 4
.text
.globl main
main: addi $sp, $sp, -4
sw $ra, 0($sp)
move $t0, $zero # t0を0に初期化
li $v0, 5
syscall # 数を聞き、読み取る。(0〜255までの8bitとする)
move $t0, $v0 # t0に入れる。割られる数
la $t4, result + 3
sb $zero, ($t4) # NUL文字をストア
print_loop:
sub $t4, $t4, 1 # 次の位置へ移動
li $t1, 160 # t1(筆算で引く数)に160を入れる
li $t2, 16 # t2(商に足す数)に16を入れる
move $t3, $zero # t3(商)を0に初期化
# 2進数で10で割る筆算
div_loop:
blt $t0, $t1, cannot_sub
# 筆算で1が立つケース
sub $t0, $t0, $t1 # 余りの計算(1bit分)
or $t3, $t3, $t2 # 商の計算(1bit分)
cannot_sub:
# 筆算で0になるケース
srl $t1, $t1, 1
srl $t2, $t2, 1
bne $t2, 0, div_loop
add $t0, $t0, 48 # 余り1桁をASCIIコードに変換
sb $t0, ($t4) # 1文字ストア
move $t0, $t3 # 商を割られる数に設定
bne $t0, 0, print_loop
# 結果の表示
move $a0, $t4
li $v0, 4
syscall
la $a0, newln # 以下改行命令
li $v0, 4
syscall
# 半角空白2つを全角空白に変換しています
言い忘れました。
64bitの割り算は自力で計算する必要があるため、乗除算を使用せず、2進数の筆算を念頭に書いています。
@deameoさん
ありがとうございます。参考にさせていただきます。BAにしたいので適当に回答を残していただきたいです。
いえいえ、多分yomoanyanさんが64bitの整数表示コードを書いたときこの問題は初めて解決すると思います。
無理に解決する必要はないですけど、その機会を奪いたくはないので、このままにさせてください。
分かりました。ちょっと今はまだ難しいかもしれないですけど、もう少し勉強したらまたやってみたいと思います。
回答3件
あなたの回答
tips
プレビュー