MIPS-パラメータとして4つ以上の文字列

ジャスティンD。

putsMIPSに実装しようとしていますで動作させました$a0そのレジスタのアドレスから始まる文字列を出力しました。ただし、現在puts、任意の量の文字列を実装しようとしています。つまり、レジスタを使用できなくなりました。スタックを効率的に使用する方法について混乱しています。私の主な手順から、任意の量の文字列をスタックします。私はその後、したいjalputsすべての文字列が印刷されますされ、。また、スタックの一番上に、印刷する文字列の数を渡します。

これが私のコードですputs

# puts - prints ASCII to the screen
#    prints from $a0, $a1, $a2, $a3 (buffers)
#    stops when chracter is NULL
#   ASSUME THAT WHEN PUTS IS CALLED, AT LEAST ONE STRING IS PASSED
#
# CALLING CONVENTION
#
# I decided not to use any of the registers $a0-$a4. 
# Instead, the caller stacks all the strings it wants to print in the stack. 
# On top of it, it adds the number of strings it wants to print.
# puts will loop, printing each string, until it has printed all of them.
#
# Since the caller is using "s" registers, puts must save them to the stack. 
# Thus, these will be put on top of the stack.
# puts will have to access the strings below the stacked registers.
#
#   ============  STACK DIAGRAM ==============
#
#   \   Number of Strings   \ TOP
#   \       String 1        \ +200      
#   \       String 2        \ +400
#   \       String 3        \ +600
#   \       String 4        \ +800
#   \       String 5        \ +/000
#   \       String 6        \ +...
#   \         ...       \ 
#
# on entry:
#   $ra -- return address
#   0($sp) -- number of strings to print
#   x($sp) -- strings to print
#
# on exit:
#   $v0 -- number of character printed
#       
    .text
puts:
    addi $sp, $sp, -20  # make room for 6 registers
    sw $ra, 16($sp)     # save $ra on the stack
    sw $s0, 12($sp)     # save $s0 on the stack
    sw, $s1, 8($sp)     # save $s1 on the stack
    sw, $s2, 4($sp)     # save $s2 on the stack
    sw, $s3, 0($sp)     # save $s3 on the stack

    lw $s0, 224($sp)    # copy address of first string inside $s0
    lw $s1, 24($sp)     # copy number of strings to print inside $s1
    move $s2, $zero     # counter for the number of strings printed
    move $s3, $zero     # counter for the number of characters sent to putchar

putsString:
**  lbu $t3, ($s0)      # load ccurrent char into #t3
    beq $t3, $zero, exitString  # exit puts if the current character is the NULL character

    move $a0, $t3       # put the character to print inside $a0, accessible by putchar
    jal putchar     # print char using putchar
    addi $s3, $s3, 1    # character count += 1
    addi $s0, $s0, 4    # increment string address by 1 word (4 bytes)
    j putsString        # Loop to print next character
exitString:
    addi $s2, $s2, 1    # increment number of strings printed
    beq $s1, $s2, exitPuts  # if # of strings to print = # of strings printed, then exit puts; else, increment # of strings printed
    addi $s0, $s0, 200  # $s0 now points to next string to print
    j putsString
exitPuts:   
    move $v0, $s4       # return number of character printed
    lw $s3, 0($sp)      # restore stack
    lw $s2, 4($sp)      # -
    lw $s1, 8($sp)      # -
    lw $s0, 12($sp)     # -
    lw $ra, 16($sp)     # -
    addi $sp, $sp, 20   # pop from stack
    jr $ra          # return

**の付いた行は、現時点では障害があります。取得しRuntime exception at 0x00400124: address out of range 0x00000000ます。

文字列をスタックに保存する方法は次のとおりです(今のところ、2つ(2つはハードコードされています)の文字列をで読み取りますgets)。

init:
    beq $s0,2,continue
    move $a0, $s2       # load buffer address into $a0          
    la $t1, limit       # - load limit into $a1             
    lb $a1, ($t1)       # - ...
    jal gets        # call gets - it will modify buffer     
    move $t0, $v0       # $t0 = string count returned by gets
moveBufferToStack:
    lbu $t1, ($s2)      # get first character inside buffer
    beqz $t1, endMoveBuffer
    sw $t1, ($sp)       # copy buffer(i) into array(i)

    addi $sp, $sp, 4    # array pointer points a position forward
    addi $s2, $s2, 4    # same for array pointer
    j moveBufferToStack
endMoveBuffer:
    addi $sp, $sp, 200  # step to next array cell 
    addi $s0, $s0, 1    # increment number of strings read
    j init          # loop until we have 9 elements
continue:           
    jal puts
    j done
RobertB

問題のある行に焦点を合わせると、次のようになります。

lw $s0, 224($sp)    # copy address of first string inside $s0
...
putsString:
lbu $t3, ($s0)      # load ccurrent char into #t3

これで、224バイトを過ぎたメモリ$s0内容がロードされました$sp私が正しく理解していれば、それは文字列の最初の4バイトです。つまり、文字列が「マダム、私はアダムです」の場合、$s0「a」「d」「a」「M」含まれます(エンディアンが正しい場合)。

したがって、を実行するlbu $t3, ($s0)と、現在の文字がロードされません$t3指す バイトをロードしています。$s0これは、メモリ内のランダムなスポットになります。文字列が空白の場合、$s00x00000000が含まれている可能性があるため、発生するエラーが生成されます。

の代わりにlwあなたがやりたいことaddi $s0, $sp, 224です。次に、$ s0は$ sp +224のアドレスを指します。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事