Язык ассемблера кодирования MIPS - прерывания

Мой код не работал после попытки. Может кто-нибудь показать мне, как это делается?

Инструкции -

Отключите задержки ветвления и загрузки для этой программы, если хотите. Это значительно упростит задачу. Обязательно включите ввод-вывод с отображением памяти. Прежде чем приступить к проектированию или программированию, убедитесь, что вы полностью понимаете, что делает пример программы ввода-вывода с отображением памяти с моего веб-сайта. Вы не будете опрашивать, но вам нужно четкое понимание операций ввода-вывода с отображением в память.

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

Напишите программу, которая начинается с двух массивов символов (для хранения строк .asciiz) одинаковой длины (не менее 60 символов), помеченных как «источник» и «отображение». Изначально сделайте исходный массив строкой символов с '\ n' перед завершающим NUL. Включите в строку прописные и строчные буквы и другие символы (знаки препинания, цифры и пробелы). Запустите вашу программу, скопировав исходный массив в дисплейный массив. Для этого используйте подпрограмму, передав адреса двух массивов в стеке. Используйте реальное соглашение о вызове подпрограмм.

После копирования строки разрешите прерывания, а затем выполните цикл, исследуя переменную (которая может быть изменена с помощью кода внутри обработчика прерывания), пока пользователь не скажет программе завершить работу. Всякий раз, когда происходит прерывание готовности вывода (передатчик), обработчик прерывания будет печатать следующий одиночный символ из массива отображения, возвращаясь к началу после того, как он напечатает '\ n'. Каждый раз, когда происходит прерывание ввода (приемник), вы извлекаете ввод пользователя (один символ) и выполняете одну из следующих задач в зависимости от ввода пользователя:

's': отсортируйте массив отображения, используя любую простую процедуру сортировки (можно использовать пузырьки или рябь). Не сортируйте '\ n'.

't': переключение регистра каждого алфавитного символа (например, 'T' становится 't', 't' становится 'T', и все неалфавитные символы остаются неизменными).

'a': снова заменить элементы массива отображения исходными элементами.

'r': поменять местами элементы в отображаемом массиве (опять же, исключая '\ n').

'q': quit - прекратить выполнение программы.

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

Команда 'q' должна просто установить переменную, которую запрашивает (повторно) основная программа, что приведет к завершению основной программы с системным вызовом с кодом 10. Вы НЕ МОЖЕТЕ использовать регистры для передачи информации между программой и прерыванием. обработчик.

Примечание: прерывание могло произойти в середине отображения массива, поэтому отображаемые символы могли изменить среднюю строку. Эта программа, очевидно, разработана с учетом предыдущих назначений, поэтому вы должны повторно использовать код везде, где это возможно. Основная новая функция - ввод и вывод, управляемые прерываниями. Вместо того, чтобы читать целые строки за один системный вызов, вы будете читать и обрабатывать каждый символ по мере его поступления. Опять же, вы НЕ МОЖЕТЕ использовать системный вызов для любого ввода-вывода. Всего это примерно три-четыре страницы кода.

Это мой код, но я не могу заставить его работать -

prompt: .asciiz "SPIM IO Test.\nOnly runs with -mapped_io flag.\nPlease type 6 input lines:\n"
nl:      .asciiz "\n"
      .text
      .globl main
main:
      li $v0 4
      la $a0 prompt
      syscall
# Register usage:
#            s0            loop counter
#            t0            address of recv_ctrl
#            t1            address of recv_buffer
#            t2            address of trans_ctrl
#            t3            address of trans_buffer
#            t4, t5            temporaries
#            t6            char read from input
#            t7            1 => char in t6
      li      $s0, 3            # loop counter
      li       $t0, 0xffff0000      # recv ctrl
      li      $t1, 0xffff0004      # recv buf
      li       $t2, 0xffff0008      # trans ctrl
      li       $t3, 0xffff000c      # trans buf
# First, read and echo 3 lines of input by polling the IO registers, not through
# interrupts:
      mtc0      $0, $12            # Clear IE bit in Status reg to disable interrupts
l1:
      lw      $t4, 0($t0)      # Wait for receiver ready
      and       $t4, $t4, 1
      beq      $t4, 0, l1
      lw      $t6, 0($t1)      # Read character
l2:
      lw      $t4, 0($t2)      # Wait for transmitter ready
      and      $t4, $t4, 1
      beq      $t4, 0, l2
      sw      $t6, 0($t3)      # Write character
      beq      $t6, 0xa, decr      # New line (nl)
      bne      $t6, 0xd, l1      # Carriage return (cr)
decr:
      add      $s0, $s0, -1      # Decrement line counter
      bne     $s0, 0, l1      # If not zero, get another line
# Second, read and echo 3 lines of input by through interrupts:
      mfc0      $t4, $13
      and      $t4, 0xffff00ff      # Clear IP bits in Cause register
      mtc0      $t4, $13
      li      $s0, 3            # loop counter
      li      $t4, 0x2      # Enable device interrupts
      sw      $t4, 0($t0)
      sw      $t4, 0($t2)
      mfc0      $t4, $12      # Enable interrupts and mask in Status reg
      ori      $t4, $t4, 0xff01
      mtc0      $t4, $12
l3:      b      l3            # Loop waiting for interrupts
# Trap handler. Replaces the standard SPIM handler.
      .ktext 0x80000180
      mfc0      $t4, $13      # Get ExcCode field from Cause reg
      srl      $t5, $t4, 2
      and      $t5, $t5, 0x1f      # ExcCode field
      bne      $t5, 0, exception
# An interrupt:
      and      $t5, $t4, 0x800      # Check for IP3 (HW 1)
      beq      $t5, 0, check_trans
# Receiver interrupt:
      lw      $t5, 0($t0)      # Check receiver ready
      and      $t5, $t5, 1
      beq      $t5, 0, no_recv_ready      # Error if receiver is not ready
      lw      $t6, 0($t1)      # Read character
      li      $t7, 1
      beq      $t6, 0xa, decr2      # New line (nl)
      bne      $t6, 0xd, next      # Carriage return (cr)
decr2:
      add      $s0, $s0, -1      # Decrement line counter
next:
      mfc0      $t4, $13      # Get Cause register
      and      $t4, 0xfffff7ff      # Clear IP3 bit
      mtc0      $t4, $13
check_trans:
      beq      $t7, 0, ret_handler      # No char to write yet
      and      $t5, $t4, 0x400      # Check for IP2 (HW 0)
      beq      $t5, 0, check_loop
# Transmitter interrupt:
      lw      $t5, 0($t2)      # Check transmitter ready
      and      $t5, $t5, 1
      beq      $t5, 0, no_trans_ready
      sw      $t6, 0($t3)      # Write character
      li      $t7, 0
      mfc0      $t4, $13      # Get Cause register
      and      $t4, 0xfffffbff      # Clear IP2 bit
      mtc0      $t4, $13
check_loop:
      bne      $s0, 0, ret_handler      # If line counter not zero, get another line
# Done echoing, so terminate program.
      li      $v0, 10
      syscall                  # syscall 10 (exit)
# Return from handler.
ret_handler:
      mfc0      $t4, $12      # Enable interrupts and mask in Status reg
      ori      $t4, $t4, 0xff01
      mtc0      $t4, $12
      eret                  # return to interrupted instruction
exception:
      li      $v0, 4            # Non-interrupt exception
      la      $a0, other_str      # Print message and ignore
      syscall
      b      ret_handler
no_recv_ready:
      li      $v0, 4            # Receiver was not ready after interrupt
      la      $a0, no_recv_str      # Print message and ignore
      syscall
      b      ret_handler
bad_int:
      li      $v0, 4            # Interrupt was not from recv or trans
      la      $a0, bad_int_str      # Print message and ignore
      syscall
      b      ret_handler
no_trans_ready:
      li      $v0, 4            # Transmitter was not ready after interrupt
      la      $a0, no_trans_str      # Print message and ignore
      syscall
      b      ret_handler
      .data
other_str:
      .asciiz "Non-interrupt exception\n"
no_recv_str:
      .asciiz "Receiver not ready\n"
no_trans_str:
      .asciiz "Transmitter not ready\n"
bad_int_str:
      .asciiz "Unknown interrupt\n"

person dao fahk    schedule 10.12.2020    source источник
comment
Не могли бы вы подробнее рассказать, как это не работает?   -  person Erik Eidt    schedule 10.12.2020
comment
он застревает в петле   -  person dao fahk    schedule 12.12.2020
comment
Хорошо, какой цикл не заканчивается?   -  person Erik Eidt    schedule 12.12.2020
comment
строка 53, где есть инструкции lw $ 12, 0 (8 $)   -  person dao fahk    schedule 15.12.2020


Ответы (1)


Я работаю над очень похожим заданием и новичок в MIPS. Просматривая программу, я думаю, что директива в коде ядра внизу pgm (строка 123) должна быть .kdata, а не .data. Также в сообщении отсутствует директива .data над main :.

person ReignStorm73    schedule 16.12.2020