参照によると、la(ロードアドレス)の擬似コードは次のように変換されます。
Pseudo : la $1, Label
lui $1, Label[31:16]
ori $1,$1, label[15:0]
しかし、MARSでコードをアセンブルしようとすると、次のエラーが発生します。
"無効な言語要素:16]
[31:16]の部分を削除すると、
「ラベル」:オペランドのタイプが正しくありません
何か案が?
これは、ラベルの最上位16ビットが$1に設定されていることを意味します。次に、16個の最下位ビットが16個の最上位ビットとor'edされます。
ここにlui命令の説明があります。レジスタにラベルアドレスの16msbビットをロードし、16lsbをゼロにします。
このようにして、32ビット命令で32ビットアドレス(mips32)をロードできます。
それは決して「実際のコード」を意図したものではありません。[31:16] / [15:0]の部分は有効なミップではなく、ビットの動きを理解するためだけにあります。
編集:あなたのコメントに応じて、lui命令を使用してロードしたいアドレスを知っている必要があります。これを行うには、ラベルを使用して目的のアドレスを示すことができます。例えば
.data
my_var: .asciiz "This is a nul terminated string"
.text
andi $a0,$a0,0x0000ffff
lui $a0,my_var
ori $a0,$a0,my_var
それは本当に良い質問です。そこで私は可能な解決策にたどり着きました。上記の答えは無条件に機能しません。
実際には、データセグメントをどこに配置するかを言うことができるはずです(たとえば、SPIMを使用するとそれが可能になります)。ディレクティブは、このデータセグメントを配置する必要がある32ビットアドレスという.data
1つのオプションの引数を取ります。このようにして、例外ハンドラーが作成されます(.kdata
の代わりにのみを使用.data
)。
例:
.data 0x10001000 #remember this location
.align 0
.asciiz "MIPS IS GREAT!" #this is at offset 0
.text
.align 2
.globl main
main: #let's assume we've got no arguments
addiu $sp, $sp, -24 #subroutine prolog
sw $ra, 16($sp)
sw $fp, 10($sp)
addiu $fp, $sp, 20
ori $v0, $0, 4
lui $a0, 0x1000 #sole argument must be str pointer
ori $a0, $a0, 0x1000
syscall #print STR out on console
lw $ra, 16($sp) #subroutine epilog
lw $fp, 10($sp)
addiu $sp, $sp, 24
jal
これが最善の解決策であるかどうかは実際にはわかりませんが、(仮想アドレッシングモード、つまりロードまたはストア命令のラベルを使用しなくても)考えられる唯一の解決策であり、このアイデアは機能するはずです(私のコード例が機能するかどうかにかかわらず、わかりません、テストしていません)。
編集:私はちょうど遊んで、疑似命令なしで、自然なアドレッシングモードでレジスタにラベルをロードすることを可能にする本当に素晴らしいトリックを発見しました。私の例:
.data 0x10001000
.word LABEL
LABEL: .asciiz "Get LABEL to print this C string."
.text
.align 2
.globl main
#test if it loads LABEL
main:
lui $4, 0x1000
ori $4, $4, 0x1000
lw $4, 0($4)
ori $2, $0, 4
syscall
SPIMではうまく組み立てられます!0x10001000のメモリを見ると、0x10001004が保存されています。このアプローチは、メモリ内にポインタを作成します。ポインターのオフセットを簡単に計算できるように、ポインターを他の可変長データの前に配置することをお勧めします。