2016-09-26 9 views
0

1桁の任意の整数をとる配列を作成しようとしています。ユーザーが-1を入力すると、ただし、最初と2番目の数値は正しく保存されています。 3回目の入力が終わったら、2番目の番号が格納されているメモリアドレスを上書きします。私のコードはMIPSです。MIPS、ダイナミックアレイ、3番目の入力が2番目の入力を上書きする

# switch to the Data segment 
    .data 
# global data is defined here 

myArray: 
    .word 256 
char: 
    .word 4 
sp: 
    .asciiz " " 
cr: 
    .asciiz "\n" 
error_string: 
    .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR." 
array_input: 
    .asciiz "\Please type a digit. Press enter after each. End array with -1 input.\n" 
neg_one: 
    .asciiz "\1-" 

# switch to the Text segment 
    .text 
    .globl main 
main: 
    # the rest of the main program goes here 
    lui $s7, 0x000a # set first half of $s7 
    ori $s7, $s7, 0x312d # set $s7 to compare with beq and exit input, $s7 = -1 now. 
    addi $t3, $t3, 0 # set counter for decrementing array later 
    la $s1, myArray # set base address of array to $s1 
    la $a0, array_input 
    jal Print_string 


input_loop: 
    la $a0, char 
    li $a1, 4 
    jal Input # prompt user for digit input 

    lb $t1, char 
    lw $t2, char # store char from buffer into t1 (does this strip newline?) 
    beq $t2, $s7, begin_sort # branch if input is equivalent to -1 


    blt $t1, 48, error  # check if char is not a digit (ascii<'0') 
    bgt $t1, 57, error  # check if char is not a digit (ascii>'9') 
    addi $t1, $t1, -48 


    sw $t1, 0($s1) # store char into array 

    move $a0, $t1 
    jal Print_integer # print number that was input 
    la $a0, cr 
    jal Print_string # print newline char 

    addi $s1, $s1, 4 # increment array address 
    addi $t3, $t3, 1 # increment array counter 
    j input_loop # jump back up when -1 not entered 

begin_sort: 
    Jal Exit 

.globl Input 
Input: # gets a string from user into register 
    addi $v0, $zero, 8 
    syscall #calls for input 
    jr $ra 

    .globl Print_integer 
Print_integer: # print the integer in register a0. Loading one into $v0 from addi makes syscall print 
    addi $v0, $zero, 1 
    syscall 
    jr $ra 

    .globl Print_string 
Print_string: # print the string whose starting address is in register a0 
    addi $v0, $zero, 4 
    syscall 
    jr $ra 

    .globl Exit 
Exit: # end the program, no explicit return status 
    addi $v0, $zero, 10 
    syscall 
    jr $ra 

は、例えば、Iは次いで5、3、8に入力し、私のアレイアドレス0x10010000値の(+0)が0x08の値(+4)では0x0A、値(+8)が0×03です。明らかに(+4)は間違っていて、ちょうど0x05でなければなりません。これは、Jal InputがSyscallを実行するまで行われていました。だから私はcharで私の住所に何か間違っていると思いますか?私のコードはファンキーになってくるので、一桁も入力できません。私もsbを​​使うことができることを知っていますが、後で操作するためにこれを4バイト保存する必要があると思います。基本的に、私のメモリアドレスをValue(+4)に上書きするのは何ですか?

答えて

0

解決方法:うわー、私は文字通りspとcrのような文字列の宣言の下にmyArrayとcharの部分を文字通り移動することでこの問題を解決しました。これは、配列のスペースを文字列の後に宣言する必要があるからです。それ以外の場合は、宣言したスペースを上書きします。その後、ダイナミックアレイを調整したときに、格納された文字列を台無しにしました。奇妙なもの。私はまだ完全な説明に感謝します。

+0

申し訳ありませんが、これは本当にバグの修正ではありません。なぜ私の答えを見てください。 –

0

あなたは間違って.wordディレクティブを使用していた。

myArray: .word  256 

これは 256個の要素を持つ配列を定義していません。 スカラーワードの初期値は256です。配列のサイズは 4バイトです。

したがって、配列に最初に格納した後で、末尾を超えて書き込んでいます(つまり、未定義の動作、C言語)。

答えではmyArray.dataセクションの最後に移動しました。しかし、ではなく、の修正です。それは単に問題を「ペーパーオーバー」するだけです。 の場合はmyArray | char、次にmyArrayの2番目の要素にはガベージデータが含まれます。

アレイを定義する正しい方法は、.spaceディレクティブを使用することです。指定された番号のバイトを予約します。だから、myArrayのための正しい定義は次のようになります。

myArray: .space  1024 

char配列は、同様の問題があったが、あなたは「運が尽きて」。

さらにいくつかのバグもありました。特に、「-1」チェックは全く機能していないと弱かった。

私はあなたのプログラムの3つのバージョンを作成しました。バグの注釈付きバージョン。清掃されて固定された秒。ユーザーの入力を得るために別のsyscallを使用するため、少し単純で、より一般的で、より効率的な3分の1です。ここで


注釈付きバージョンは、[無償スタイルのクリーンアップをご容赦ください]である。ここで

# switch to the Data segment 
    .data 
    # global data is defined here 

    # NOTE/BUG: this defines a _single_ 32 bit word [with initial value of 256] 
    # and _not_ an array with 256 elements 
    # as it is, myArray is only 4 bytes long 
myArray: .word  256 

    # NOTE/BUG: this has similar problems to above but you luck out because 
    # it defines an area of length 4 by virtue of the .word directive and _not_ 
    # the 4 
char:  .word  4 

sp:   .asciiz  " " 
cr:   .asciiz  "\n" 
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR." 
array_input: .asciiz "\Please type a digit. Press enter after each. End array with -1 input.\n" 

    # NOTE/BUG: this string is incorrect for its intended use below 
    # NOTE/BUG: this isn't used 
neg_one: .asciiz  "\1-" 

# switch to the Text segment 
    .text 
    .globl main 

    # the rest of the main program goes here 
main: 
    # NOTE/BUG: this is a poor way to initialize this. use "li" or "lw" instead 
    # but also see below 
    # NOTE/BUG: manually compensating for little endian is tedious 
    lui  $s7,0x000a    # set first half of $s7 
    ori  $s7,$s7,0x312d   # set $s7 to compare with beq and exit input, $s7 = -1 now. 

    # NOTE/BUG: this has _no_ effect 
    addi $t3,$t3,0    # set counter for decrementing array later 

    la  $s1,myArray    # set base address of array to $s1 

    # NOTE/BUG: although not a bug, this should be part of the loop 
    la  $a0,array_input 
    jal  Print_string 

input_loop: 
    la  $a0,char 
    li  $a1,4 
    jal  Input     # prompt user for digit input 

    lb  $t1,char 

    # NOTE/BUG: this is a weak way to check for -1 
    lw  $t2,char    # store char from buffer into t1 (does this strip newline?) 
    beq  $t2,$s7,begin_sort  # branch if input is equivalent to -1 

    blt  $t1,48,error   # check if char is not a digit (ascii<'0') 
    bgt  $t1,57,error   # check if char is not a digit (ascii>'9') 
    addi $t1,$t1,-48 

    sw  $t1,0($s1)    # store char into array 

    move $a0,$t1 
    jal  Print_integer   # print number that was input 

    la  $a0,cr 
    jal  Print_string   # print newline char 

    addi $s1,$s1,4    # increment array address 
    addi $t3,$t3,1    # increment array counter 
    j  input_loop    # jump back up when -1 not entered 

begin_sort: 
    # NOTE/BUG: this _must_ be "jal" and _not_ "Jal" 
    # NOTE/BUG: this should just be "j" or just move the "Exit" code here 
    Jal  Exit 

error: 
    la  $a0,error_string 
    li  $v0,4 
    syscall 
    j  input_loop 

    .globl Input 
# gets a string from user into register 
Input: 
    addi $v0,$zero,8 
    syscall       # calls for input 
    jr  $ra 

    .globl Print_integer 
# print the integer in register a0. Loading one into $v0 from addi makes syscall print 
Print_integer: 
    addi $v0,$zero,1 
    syscall 
    jr  $ra 

    .globl Print_string 
# print the string whose starting address is in register a0 
Print_string: 
    addi $v0,$zero,4 
    syscall 
    jr  $ra 

    .globl Exit 
# end the program, no explicit return status 
Exit: 
    addi $v0,$zero,10 
    syscall 
    jr  $ra 

はクリーンアップと作業バージョンです。最良の方法はやっていることに注意してください「-1」のチェックは、改行を削除してstrcmp機能を実装することですが、私はやったシンプルな何か上記のプログラムはまだその中に制限を受ける

# switch to the Data segment 
    .data 
    # global data is defined here 

myArray: .space  1024 
eArray: 

char:  .space  80 
echar: 

sp:   .asciiz  " " 
cr:   .asciiz  "\n" 
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR." 
array_input: .asciiz "\Please type a digit. Press enter after each. End array with -1 input.\n" 

# switch to the Text segment 
    .text 
    .globl main 

    # the rest of the main program goes here 
main: 
    la  $s1,myArray    # set base address of array to $s1 
    la  $s2,eArray    # get end of array 

input_loop: 
    # prompt user 
    la  $a0,array_input 
    jal  Print_string 

    # read in user's response 
    # NOTE: unless you are _required_ to decode the number yourself, using 
    # syscall 5 (read integer) is _much_ simpler 
    la  $a0,char 
    la  $a1,echar 
    subu $a1,$a1,$a0 
    jal  Input     # prompt user for digit input 

    # check for -1 on input 
    lb  $t2,0($a0)    # is first char "-"? 
    bne  $t2,0x2D,not_negone  # no, fly 
    lb  $t2,1($a0)    # is second char "1"? 
    bne  $t2,0x31,not_negone  # no, fly 
    lb  $t2,2($a0)    # is third char "\n"? 
    beq  $t2,0x0A,begin_sort  # yes, fly 

not_negone: 
    lb  $t1,0($a0) 
    blt  $t1,48,error   # check if char is not a digit (ascii<'0') 
    bgt  $t1,57,error   # check if char is not a digit (ascii>'9') 
    addi $t1,$t1,-48 

    sw  $t1,0($s1)    # store char into array 

    move $a0,$t1 
    jal  Print_integer   # print number that was input 

    la  $a0,cr 
    jal  Print_string   # print newline char 

    addi $s1,$s1,4    # increment array address -- over edge? 
    blt  $s1,$s2,input_loop  # no, loop 

begin_sort: 
    j  Exit 

error: 
    la  $a0,error_string 
    li  $v0,4 
    syscall 
    j  input_loop 

# gets a string from user into register 
Input: 
    li  $v0,8 
    syscall       # calls for input 
    jr  $ra 

# print the integer in register a0. Loading one into $v0 from addi makes syscall print 
Print_integer: 
    li  $v0,1 
    syscall 
    jr  $ra 

# print the string whose starting address is in register a0 
Print_string: 
    li  $v0,4 
    syscall 
    jr  $ra 

# end the program, no explicit return status 
Exit: 
    li  $v0,10 
    syscall 

入力する数字は1桁のみです。一般的な解決策は、atoiに相当するものを実装することです。

しかし、あなたはsyscall#5を使用して、独自の数値解析を行うためにを必要としていない場合は、[整数を読む]はるかに簡単ですが、任意の整数が可能になり、ほとんどのMIPSプログラムが使用するものです。

# switch to the Data segment 
    .data 
    # global data is defined here 

myArray: .space  1024 
eArray: 

sp:   .asciiz  " " 
cr:   .asciiz  "\n" 
error_string: .asciiz "\ONE DOES NOT SIMPLY WALK INTO MORDOR." 
array_input: .asciiz "\Please type a number. Press enter after each. End array with -1 input.\n" 

# switch to the Text segment 
    .text 
    .globl main 

    # the rest of the main program goes here 
main: 
    la  $s1,myArray    # set base address of array to $s1 
    la  $s2,eArray    # get end of array 

input_loop: 
    # prompt user 
    la  $a0,array_input 
    jal  Print_string 

    # read in user's response 
    li  $v0,5 
    syscall 
    move $t1,$v0 

    # check for -1 on input 
    bltz $t1,begin_sort 

    sw  $t1,0($s1)    # store char into array 

    move $a0,$t1 
    jal  Print_integer   # print number that was input 

    la  $a0,cr 
    jal  Print_string   # print newline char 

    addi $s1,$s1,4    # increment array address -- over edge? 
    blt  $s1,$s2,input_loop  # no, loop 

begin_sort: 
    j  Exit 

error: 
    la  $a0,error_string 
    li  $v0,4 
    syscall 
    j  input_loop 

# gets a string from user into register 
Input: 
    li  $v0,8 
    syscall       # calls for input 
    jr  $ra 

# print the integer in register a0. Loading one into $v0 from addi makes syscall print 
Print_integer: 
    li  $v0,1 
    syscall 
    jr  $ra 

# print the string whose starting address is in register a0 
Print_string: 
    li  $v0,4 
    syscall 
    jr  $ra 

# end the program, no explicit return status 
Exit: 
    li  $v0,10 
    syscall 
+0

これは私の理解を大いに助けました。あなたの完全な入力をありがとう! –

関連する問題