BMSTU/02-dspmd-02-hw-var-lama.tex

119 lines
6.9 KiB
TeX
Raw Normal View History

2023-01-27 22:32:16 +03:00
\documentclass[a4paper,fontsize=14bp]{article}
\input{../common-preamble}
\input{../fancy-listings-preamble}
\input{../bmstu-preamble}
\numerationTop
\begin{document}
\thispagestyle{empty}
\makeBMSTUHeader
Официальное описание из комментария к функции хорошо объясняет, что именно она делает:
\begin{verbatim}
Description: minimum Value and Index of the minimum
element of a vector
\end{verbatim}
Снаружи функция будет вызываться вот так
\begin{verbatim}
void minvec (DATA *x, ushort nx, DATA *val, DATA *idx)
\end{verbatim}
То есть передадим
\begin{itemize}
\item вектор (массив чисел) \code{DATA *x}, важно, что вектор у нас из типа \code{DATA}, который, на самом деле \code{ushort (unsigned short)}, 16-разрядный, то есть при подсчёте сдвига по вектору для получения следующего значения - нужно смещаться на 2 байта.
\item длину вектора \code{ushort nx},
\item указатель на полученное значение \code{DATA *val},
\item указатель на полученный индекс \code{DATA *idx}.
\end{itemize}
Для языка ассемблера, умеющего манипулировать только регистрами, важно понимать, в какие именно регистры будут положены эти параметры
\begin{itemize}
\item \code{DATA *x} - указатель AR0
\item \code{ushort nx} - регистр T0
\item \code{DATA *val} - указатель AR1
\item \code{DATA *idx} - указатель AR2
\end{itemize}
дальше последовательно опишем что именно делает функция и как:
\begin{verbatim}
.text
.global _minvec
_minvec:
\end{verbatim}
до вызова функции система находилась в каком-то статусе, соответственно, нам нужно этот статус сохранить, чтобы наша функция ничего не сломала
\begin{verbatim}
PSH mmap(ST0_55) ; Сохранение регистров статуса на стеке
PSH mmap(ST1_55)
PSH mmap(ST2_55)
PSH mmap(ST3_55)
\end{verbatim}
далее происходит одновременное действие, знак \code{II} показывает, что два этих действия будут выполняться параллельно. Запись очередного значения из вектора во временный регистр \code{AC1} и вычитание 2 из регистра \code{T0}. Запись \code{*AR0+} означает, что мы не только разыменовали указатель (получили значение по указателю, знак *), но и сдвинули указатель вектора на следующий адрес (знак +)
\begin{verbatim}
MOV *AR0+,AC1
|| SUB #2,T0
\end{verbatim}
Сохраним значение из \code{T0} в \code{BRC0} и одновременно запишем 0 в \code{AR3}. Это вспомогательное действие, чтобы высвободить регистры, при помощи которых мы будем делать дальнейшие вычисления.
\begin{verbatim}
MOV T0,BRC0
|| MOV #0,AR3
\end{verbatim}
Далее происходит обнуление регистра \code{T0} и цикл между значением \code{RPTBLOCAL} и \code{end_block:}
\begin{verbatim}
MOV #0,T0
|| RPTBLOCAL end_block-1
\end{verbatim}
В цикле мы кладём следующее значение из вектора в \code{AC0}, помнишь, мы уже клали значение из вектора в \code{AC1}, вот теперь в \code{AC0}. Мнемоника \code{MAR} в явном виде не описана в документации, но есть предположение, что MAR это аббревиатура от Modify Auxiliary Register, то есть по факту это просто увеличение временного указателя на будущий вычисленный индекс на единицу. Напомню, в этот регистр два шага назад, до цикла, мы положили 0, то есть, скорее всего, это будет конечный индекс в векторе, который мы должны вернуть.
\begin{verbatim}
MOV *AR0+,AC0
|| MAR *AR3+
\end{verbatim}
Тут, понятно, мы ищем минимальное из двух значений (мы же положили последовательно два значения из вектора в \code{AC0} и \code{AC1}). Значение, полученное в результате сравнения, будет положено в \code{AC1}\footnote{TMS320C55x-Mnemonic Instruction Set. Reference Guide-2009, p.428}. То, что мы положим минимальное в \code{AC1} даст нам возможность на следующей итерации цикла снова сравнивать с ним прочитанное в \code{AC0} следующее значение из вектора, как мы это делаем на предыдущем шаге.
\begin{verbatim}
MIN AC0,AC1
\end{verbatim}
Это проверка условия завершения цикла \footnote{TMS320C55x-Mnemonic Instruction Set. Reference Guide-2009, p.749 (XCCPART), p.20(CARRY)} по биту переноса и одновременно вывод информации из \code{AR3} (в котором, напомню, у нас хранился индекс минимального значения в векторе) по указателю \code{AR2}, который, напомню, нам передали с параметрами функции
\begin{verbatim}
XCCPART end_block, !CARRY
|| MOV AR3,*AR2
\end{verbatim}
По завершении цикла, сохраним полученное значение минимума по указателю \code{AR1}, который мы передали снаружи в параметре \code{val}.
\begin{verbatim}
end_block:
MOV AC1,*AR1
\end{verbatim}
Вернём на место статус системы из сохранённого ранее и выйдем из функции
\begin{verbatim}
POP mmap(ST3_55)
POP mmap(ST2_55)
POP mmap(ST1_55)
POP mmap(ST0_55)
RET
\end{verbatim}
\begin{lstlisting}[language=C,style=CCodeStyle]
void minvec (DATA *x, ushort nx, DATA *val, DATA *idx) {
while (nx-- >= 0) {
if (*val > *(x + nx)) {
*val = *(x + nx);
*idx = nx;
}
}
}
\end{lstlisting}
\end{document}