2017-10-09 11 views
0

私は単にコンソールからの入力から文字列を読み込もうとしています。私はxspimを実行してシミュレーションを実行していますが、これは裸のモードで実行する必要があります。擬似命令を使用できないことを意味し、オンラインで見つかった多くのことが擬似命令でを実行する方法です。私が読んでいるすべてのドキュメントでは、 "la"命令を使用して$ a0に文字列を格納するように指示していますが、その命令は利用できません。私はその命令が何を翻訳するかについて読んで、効果的に "lui"に続いて "ori"に変わった。私を投げ捨てる部分は、最初のデータ位置(常に0x 1000 0000)と文字列の最初のバイトのアドレスの間のバイト数を入力することになっています。私の文字列の最初のバイトが何であるか分かりません。 RISCマシン用ベアモード(ラ・擬似命令なし)で動作するMIPSの静的データのアドレスを取得する方法

.globl main 
.globl done 
.globl convert 

.data 
prompt: .asciiz "Enter a decimal number, to quit type 'quit':" #45 
result: .asciiz "The number you entered is " #72 
input: .space 64 

.text 
convert: 


main:  addi $v0, $0, 4   #Print prompt to enter number 
      lui $a0, 0x1000   #Address of prompt 
      syscall     #Display prompt 

      addi $v0, $0, 8   #Setting up syscall to read in string 
      lui $at, 4097 
      ori $a0, $at, input  #Where I want my string to be stored 
      addi $a1, $0, 64  #How long my string will be 
      syscall     #Syscall to read in string 
+0

スタック上のバ​​ッファ(入力バッファ用)を使用して回避することができます。 –

答えて

0

通常のアセンブラ+リンカーは半分に分割アドレスをサポートし、そのアドレスのみ、リンク時定数ではないと組み立て-時間を持っているので、あなたは、lui $reg, upper(input)ori $reg, $reg, lower(input)を書くことができます:ここでは、私が持っているものです。例えば

、あなたがMIPS gcc's assembly output on Godboltgcc -O3 -S、リンクされたバイナリを逆アセンブルしない)を見れば:lwの代わりに、完全なアドレスを生成する際のオフセットとしてbarがアドレスのLOの半分を使用することを

int my_global; 
int *foo() { return &my_global; } 
    lui  $2,%hi(my_global) 
    j  $31 
    addiu $2,$2,%lo(my_global) # branch-delay slot (SPIM doesn't have a branch-delay slot, but real MIPS does) 

int bar() { return my_global; } 
    lui  $2,%hi(my_global) 
    lw  $2,%lo(my_global)($2) 
    j  $31 
    nop 

    .section  .bss,"aw",@nobits 
    .align 2 
    .type my_global, @object 
    .size my_global, 4 
my_global: 
    .space 4 

お知らせロード命令でオフセットの0を使用します。


便利な最適化あなたは2つのアドレスが同一の64kブロック内にいることを知っている場合、別のori低半分定数と同じlui結果を再利用することです。 あなたのデータがここにあると思います。 Mars guarantees that syscall preserves all registers except the result;私はSPIMが同じであると仮定します。


あなたは(あなたを助けるために、リンカなし)を手動を、それをしなければならない場合は、[はい、あなたはあなたのデータの絶対アドレスを知っている必要があります。

あなたのケースでは、CRTスタートアップコードなど、そのデータを.dataセクションに置くものはありません。 .dataセクションの内容は、実行可能ファイルのデータセグメントの最初の部分にであるため、prompt:のアドレスは0x1000 0000となります。

パッディングやアライメントを要求していないため、取得できません。あなたのデータは一緒にパックされた出力に組み立てられます。 (char prompt[45], result[];が連続であることの保証はありませんCとは異なり。)

私はSPIMを使用していないが、うまくいけば、それはあなたがresult-promptinput-promptを書くようになります。

main: 
     addi $v0, $0, 4   #Print prompt to enter number 
     lui $a0, 0x1000   #Address of prompt 
     syscall     #Display prompt 

     # $a0 still holds 0x1000 << 16 
     addui $a0, $a0, input-prompt  #buffer address 
     addi $a1, $0, 64     # length 

     addi $v0, $0, 8   #syscall 8 = read string 
     syscall     #read_string(input, 64) 

     addui $t0, $a0, 0  # copy pointer to input 
     addui $a0, $a0, result - input # offset pointer again to point to the output message. 

またはその代わりに別のレジスタへのポインタをコピーするのは、あなたがアクセスinput[]に使うすべてのlb/sbのオフセットにinput-resultを追加することによって最適化することができます。

関連する問題