Почему эта программа SPIM / MIPS для суммирования четных чисел в массиве не работает? - PullRequest
0 голосов
/ 19 апреля 2019

Я новичок в MIPS, поэтому, если вы видите что-то, что не имеет смысла, то вот почему.

Я пытаюсь суммировать только четные значения массива в моем коде, изатем вставьте результат в 10 долларов.Я включил то, что я написал до сих пор.Когда программа выполняется, она зависает и выдает мне несколько ошибок: «Возникла исключительная ситуация на ПК = 0x0040001c» и «Неверный адрес в считывании данных / стека 0x10040000» и «Попытка выполнить не-инструкцию при 0x80000180.»

.text

.globl main


main:

lui $16,0x1000
lw  $17,0($16)
addiu $16, $16, 4
addiu $18, $0, 2
addiu $19, $0, 32

loop:

beq $16, $19, exit
sll $0, $0, 0
lw  $17,0($16)
sll $0, $0, 0
div $17, $18
mfhi $13
beq $13, $0, even
sll $0, $0, 0
addiu $16, $16, 4
j loop
sll $0, $0, 0

even:

add $10, $10, $17
addiu $16, $16, 4

j loop
sll $0, $0, 0

exit:

sll $0, $0, 0

.data
size: .word 8
array: .word 23, -12, 45, -32, 52, -72, 8, 13   

Я получаю -56 за 10 долларов, но результат должен быть 25 за 10 долларов.

Ответы [ 2 ]

1 голос
/ 19 апреля 2019

Есть много проблем с вашим кодом.
1. вы не читаете массив или размер, чтобы получить параметры ваших данных
2. ваш цикл управления неверен.Вы используете $ 16 (предполагается, что @array и инициализированы в 1k), добавляете 4 и тестируете, когда он достигает 32 ... Я бы действительно советовал вам иметь отдельные отдельные регистры для подсчета итераций цикла и для вычисления адресов массивов
4.Вы должны вызвать exit () (syscall 10) в конце, иначе ваш симулятор попытается выполнить ваши данные и выдаст «Попытка выполнить не-инструкцию в ...».
5. организация вашей программы со многимиветки сложны и подвержены ошибкам.Помещение циклических тестов в конец и инвертирование обычно приводит к более четкому коду.
6. Почему вы вставляете все эти nops (sll $0, $0, 0)?Большинство из них не требуются, и я бы не советовал вам использовать отложенные нагрузки для изучения mips.Как только вы овладеете им, это уже другая история.
7. Проверка, является ли число нечетным или даже не требует деления.Просто проверьте значение его LSB.

Вот рабочий код:

.text
.globl main
main:
        la $16,array   # $16==@array
        la $19,size    # $19 =@size
        lw $19,0($19)  # $19=size of array(in words)
        addi $20, $0,0 # i=0
loop:
        lw  $17,0($16)    # $17=*array
        andi $13,$17,1    # get lsb to know is $17 is odd or even
        bne $13, $0, odd  # skip accumulation if $17 is odd
        add $10, $10, $17 # accumulate sum of evens
odd:    
        addiu $16, $16, 4 # array++
        addiu $20,$20,1   # i++
        bne $20, $19, loop# goto loop if i!= size

exit:
        addi $2,$0,10    # write 10 in $v0 ($2) to call
        syscall          # syscall 10 (exit)

.data
size:  .word 8
array: .word 23, -12, 45, -32, 52, -72, 8, 13
1 голос
/ 19 апреля 2019

Первый выпуск:

Я предполагаю, что lui $16,0x1000 предназначен для начала памяти пользователя для получения размера, массива и т. Д., И lw $17,0($16) получения размера в $ 17

Использование этого

$ 16 = 0x10000000 $ 17 = 0

И, очевидно, все остальные чтения из массива в $ 16 будут неправильными.

Если я использую la $16, size, Я получаю:

$ 16 = 0x10010000 $ 17 = 8

И другие чтения для массива должны быть лучше.

Следующий выпуск:

beq $16, $19, exit is 'goto exit, если $ 16 (текущий адрес в массиве, в котором вы находитесь) == $ 19, для которого вы установили значение 32, поэтому он не собирается завершать работу в ближайшее время, и при попытке доступа к памяти это не должно быть

Другие примечания: sll $0, $0, 0 ничего не делает $ 0 = 0 << 0 - не уверен, что вы думаете, что он делает </p>

...