Есть ли в MIPS эффективный способ хранения чисел с плавающей запятой в динамически распределенном массиве? - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь сохранить список чисел с плавающей запятой в динамическом массиве, используя MIPS.Программа запрашивает у пользователя количество поплавков, которое нужно ввести, а затем зацикливается при получении ввода.

С целыми числами я знаю, как это сделать, но мне трудно заставить его работать с поплавками.Вот что у меня есть сейчас.

Получает количество вводимых чисел и соответственно распределяет память:

#get number of floats to be entered
li $v0, 5
syscall
move $t0, $v0      #t0 is number of floats

#allocate the memory required
sll $a0, $v0, 2
li $v0, 9
syscall

Это цикл, в котором я собираю числа:

move $t1, $zero #idx for loop
move $t2, $v0 #t2 is address of dynamic memory

loop:
    bge $t1, $t0, done #idx check 

    li $v0, 4
    la $a0, prompt #prompt user input
    syscall

    # read in and store int
    li $v0, 6
    syscall
    sw $v0, 0($t2)

    addi $t1, $t1, 1   # ++idx
    addi $t2, $t2, 4   #add four to move to next memory location
    j loop

done:

Вывод здесь равен всего 0,0 для любого числа с плавающей точкой, которое вводится, когда это должны быть введенные пользователем числа.Я предполагаю, что я должен хранить их неправильно.Есть ли лучший способ ввести поплавки, чем этот?

Ответы [ 2 ]

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

Значения с плавающей запятой обычно занимают регистры от $ f0 до $ f31, которые полностью отделены от $ 0 (AKA $ ноль) до $ 31 (AKA $ ra).

Вы загружаете и сохраняете эти регистры с плавающей запятой, используя инструкции lwc1 / swc1 (для одинарной точности) и ldc1 / sdc1 (для двойной точности). Это очень похоже на использование инструкций lw / sw.

Также обратите внимание, что регистры с плавающей запятой являются 32-битными на классических процессорах MIPS, и поэтому значения двойной точности занимают смежные регистры (то есть, вы можете иметь не более 16 значений двойной точности в регистрах с плавающей запятой в любой момент времени) , При использовании ldc1 / sdc1 (и любой арифметической инструкции с плавающей запятой) для двойной точности вы указываете четное ($ f0, $ f2, ..., $ f30) и следующее ($ f1, $ f3,. .., $ f31) неявно участвует.

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

Плавающие и двойные не в обычных целочисленных регистрах. У них есть свои регистры $f0..$f31.

syscall 6syscall 7 для двойников) возвращает их результаты в $f0 (не $v0), в то время как syscall 2 и syscall 3, которые печатают числа с плавающей запятой и двойники, ожидают свой аргумент в $f12.

Копирование операндов в и из плавающих регистров не выполняется с lw и sw. Вы должны использовать вместо:

  • lwc1 (Загрузить слово в сопроцессор 1) lwc1 ft, offset(base reg)
  • ldc1 (двойная загрузка в сопроцессор 1) ldc1 ft, offset(base reg)
  • swc1 (Сохранить Word от сопроцессора 1) swc1 ft, offset(base reg)
  • sdc1 (Store Double to Coprocessor 1) sdc1 ft, offset(base reg)

Итак, ваш код должен быть:

move $t1, $zero #idx for loop
move $t2, $v0 #t2 is address of dynamic memory

loop:
    bge $t1, $t0, done #idx check 

    li $v0, 4
    la $a0, prompt #prompt user input
    syscall

    # read in and store floats
    li $v0, 6
    syscall
    swc1 $f0, 0($t2)  # read float is in $f0 

    addi $t1, $t1, 1   # ++idx
    addi $t2, $t2, 4   #add four to move to next memory location
    j loop

done:
...