2016-09-26 8 views
0

임의의 숫자의 정수를 사용하는 배열을 만들려고합니다. 사용자가 -1을 입력하면 더 이상 사용하지 않습니다. 그러나 첫 번째와 두 번째 숫자는 올바르게 저장됩니다. 세 번째 입력에 대해 syscall을하면 두 번째 번호가 저장된 메모리 주소를 덮어 씁니다. 다음은 MIPS 코드입니다.MIPS, 동적 배열, 세 번째 입력이 두 번째를 덮어 씁니다.

# 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)이다은 0x03이다. 분명히 (+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의 두 번째 요소에는 가비지 데이터가 포함됩니다.

배열을 정의하는 올바른 방법은 .space 지시문을 사용하는 것입니다. 지정된 수의 바이트을 예약합니다. 그래서, myArray에 대한 올바른 정의는 다음과 같습니다

myArray: .space  1024 

char 배열은 비슷한 문제가 있었다, 그러나 당신은 "운도 참 좋아."

버그도 몇 가지 더 있습니다. 특히, "-1"수표는 전혀 효과가 없었다면 약했다.

나는 프로그램의 세 가지 버전을 만들었습니다. 주석이 달린 버전. 두 번째는 정리되고 고정됩니다. 세 번째는 사용자 입력을 얻기 위해 다른 syscall을 사용하기 때문에 조금 더 간단하고, 더 일반적이며, 더 효율적입니다.

# 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 

숫자 입력은 한 자리 숫자 만 가능합니다. 일반적인 해결책은 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

이것은 내 이해를 크게 도왔습니다. 철저한 의견을 보내 주셔서 감사합니다! –