% 
% Report description
%
% authors:
%   Χρήστος Χουτουρίδης ΑΕΜ 8997
%   cchoutou@ece.auth.gr


% Document configuration
\newcommand{\ClassName}{Μικροεπεξεργαστές και Περιφερειακά}
\newcommand{\DocTitle}{1η Εργασία}
\newcommand{\InstructorName}{Παπαευσταθίου Ιωάννης}
\newcommand{\InstructorMail}{ygp@ece.auth.gr}
\newcommand{\CurrentDate}{\today}

\input{config/AuthReportConfig.tex}

%\renewcommand{\AuthorName}{Χρήστος Χουτουρίδης}
%\renewcommand{\AuthorMail}{cchoutou@ece.auth.gr}
%\renewcommand{\AuthorAEM}{8997}

\setFancyHeadLR{\ClassName}{\DocTitle}
%\setFancyHeadLERO{\ClassName}{\DocTitle}

% Document
% =================
\begin{document}

\FirstPage

%\tableofcontents
%\listoffigures
%\listoftables

\section{Εισαγωγή}
Στην παρούσα εργασία το ζητούμενο είναι η υλοποίηση μιας ρουτίνας σε γλώσσα \eng{assemblly ARM,} που να ελέγχει αν ένα αλφαριθμητικό είναι παλίνδρομο, αλλά και η ενσωμάτωση αυτής σε ένα πρόγραμμα σε γλώσσα \eng{C.}
Για την εργασία χρησιμοποιήσαμε το εργαλείο \eng{Keil uVision} και μιας και δεν αντιμετωπίσαμε κάποιο ιδιαίτερο πρόβλημα, η αναφορά αυτή θα αναλωθεί κυρίως στην υλοποίηση και τον έλεγχο του προγράμματος.
Τον κώδικα της εργασίας αλλά και της παρούσας αναφοράς μπορείτε να βρείτε ακόμα στο προσωπικό \href{https://git.hoo2.net/hoo2/micro_assign_1}{αποθετήριο της εργασίας}.

\section{Παραδοτέα}
Στο παραδοτέο \eng{.zip} αρχείο μπορείτε να βρείτε:
\begin{itemize}
    \item Το αρχείο \textbf{\eng{main.c}} που περιέχει όλο τον ζητούμενο κώδικα της εργασίας.
    \item Το αρχείο \textbf{\eng{report.pdf}} που είναι παρούσα αναφορά.
    \item Τον κατάλογο \textbf{\eng{Keil}} που περιέχει το \eng{project} στο \eng{Keil} που χρησιμοποιήσαμε.\\
    Στο \eng{project} αυτό περιέχονται επιπλέων οι ρυθμίσεις καθώς και τα αρχεία από τη βιβλιοθήκη \eng{CMSIS} που χρειάστηκαν για την ορθή αρχικοποίηση και αλληλεπίδραση με τον επεξεργαστή.
\end{itemize}

\section{Υλοποίηση}
Η υλοποίηση του ελέγχου αν ένα αλφαριθμητικό είναι παλίνδρομο έγινε σε δύο συναρτήσεις, την \eng{\textit{isPalindrome()}} και την \eng{\textit{strLength()},} που λειτουργεί ως βοηθητική συνάρτηση.
Οι συναρτήσεις αυτές είναι υλοποιημένες σε γλώσσα \eng{assemblly} αλλά η κλήση τους από το κυρίως πρόγραμμα δεν διαφέρει καθόλου από την κλήση μιας οποιασδήποτε άλλης συνάρτησης σε γλώσσα \eng{C.}
Για τον λόγο αυτό δεν θα ασχοληθούμε περαιτέρω με το κύριο πρόγραμμα (συνάρτηση \eng{main).}

\subsection{Συνάρτηση \eng{\textit{isPalindrome()}}}
\WrapFigure{0.42}{r}{fig:isPalindrome}{isPalindrome.png}{Διάγραμμα ροής της συνάρτησης \eng{\textit{isPalindrome()}}}
Για τη συνάρτηση αυτή χρησιμοποιήσαμε ένα απλό \eng{O(n)} σειριακό αλγόριθμο, ο οποίος απαιτεί το μήκος του αλφαριθμητικού εισόδου προτού εισέλθει στον κύριο βρόχο επανάληψης.
Για να βρούμε το μήκος χρησιμοποιούμε μια ξεχωριστή συνάρτηση.
Αυτή την υλοποιήσαμε από την αρχή ώστε να μην χρειαστεί να χρησιμοποιηθεί η συνάρτηση \eng{\textit{strlen()}} της \eng{\textit{libc}.}

\par Όπως φαίνεται και στο διάγραμμα του σχήματος \ref{fig:isPalindrome}, στον κύριο βρόχο της συνάρτησης χρησιμοποιούμε δύο απαριθμητές \eng{i, j} χρησιμοποιώντας τους καταχωρητές \eng {R1, R2} αντίστοιχα και ένα δείκτη στη διεύθυνση του αλφαριθμητικού χρησιμοποιώντας τον καταχωρητή \eng{R0.}
Ο ένας δείκτης εκκινεί από την αρχή του αλφαριθμητικού και ο άλλος από το τέλος.
Σε κάθε επανάληψη διαβάζουμε από το αλφαριθμητικό τα \eng{src[i]} και \eng{src[j]} και ελέγχουμε αν είναι ίσα.
Αν δεν είναι τότε το αλφαριθμητικό δεν είναι παλίνδρομο.
Αν είναι τότε μεταθέτουμε το \eng{i} μία θέση δεξιά και το \eng{j} μία θέση αριστερά και επανεκτελούμε τον βρόχο.
Ο βρόχος συνεχίζει όσο το \eng{i} είναι μικρότερο από το \eng{j.}
Αν το \eng{i} γίνει ίσο ή μεγαλύτερο από το \eng{j,} τότε ο βρόχος τερματίζει.
Σε αυτή την περίπτωση το αλφαριθμητικό είναι παλίνδρομο.

\par Αν το αλφαριθμητικό έχει μηδενικό μήκος, τότε ο βρόχος δεν θα εκτελεστεί ούτε μία φορά και η συνάρτηση θα επιστρέψει ότι το αλφαριθμητικό είναι παλίνδρομο.
Έχουμε κάνει δηλαδή την θεώρηση ότι \textbf{\textit{τα μηδενικού μήκους αλφαριθμητικά είναι παλίνδρομα}}, καθώς είναι τα ίδια είτε τα κοιτάς από μπροστά είτε τα κοιτάς από πίσω.
Στην περίπτωση που η είσοδος της συνάρτησης είναι εκτός πεδίου ορισμού, δηλαδή ο \eng{NULL pointer,} τότε η συνάρτηση επιστρέφει ψευδές αποτέλεσμα.
Ο έλεγχος του δείκτη εισόδου γίνεται στην αρχή της συνάρτησης πριν καν γίνει η κλήση για το μήκος, προστατεύοντας έτσι κάποιο \eng{exception} από το \eng{dereference} του δείκτη στην εντολή \eng{LDR.}

\subsection{Συνάρτηση \eng{\textit{strLength()}}}
Η υλοποίηση της \eng{\textit{strLength()}} είναι επίσης ένας σειριακός αλγόριθμος.
Εδώ χρησιμοποιούμε τον καταχωρητή \eng{R1} ώς δείκτη στο αλφαριθμητικό και με αυτόν κάνουμε ανάγνωση της μνήμης, αυξάνοντάς τον ταυτόχρονα μετά από κάθε ανάγνωση.
Η συνάρτηση επιστρέφει τον αριθμό των αναγνώσεων που χρειάστηκαν μέχρι να λάβουμε το νούμερο '0', το οποίο σηματοδοτεί το τέλος του αλφαριθμητικού.

\par Ομοίως και εδώ κάνουμε έλεγχο της εισόδου ώστε αυτή να μην είναι ο \eng{NULL pointer.}
Φυσικά αυτό στη δική μας περίπτωση δεν είναι απαραίτητο καθώς υπάρχει ο αντίστοιχος έλεγχος στην \eng{\textit{isPalindrome()}} προτού την κλήση.
Παρόλα αυτά το θεωρούμε καλή πρακτική, καθώς αυτό καθιστά την \eng{\textit{strLength()}} πιο ολοκληρωμένη συνάρτηση και μια χρήση της στο μέλλον δεν θα προκαλέσει εκπλήξεις.

\subsection{Εγγραφή του αποτελέσματος στη μνήμη}
\WrapFigure{0.23}{l}{fig:ram_layout}{RAM_layout.png}{Διάταξη της μνήμης}
Η συνάρτηση \eng{\textit{isPalindrome()}} αφού εκτελεστεί, επιστρέφει μια τιμή στον \eng{caller.}
Στα ζητούμενα όμως της εργασίας ήταν η συνάρτηση αυτή να γράφει το αποτέλεσμα και σε μία θέση μνήμης της επιλογής μας.
Αυτό υπό κανονικές συνθήκες είναι ανεπίτρεπτο.
Για τα πλαίσια όμως της εργασίας προσπαθήσαμε να ανταπεξέλθουμε με ένα σχετικά ασφαλή τρόπο.

\par Όπως φαίνεται και στο σχήμα \ref{fig:ram_layout}, o συνδέτης \eng{(linker)} του εργαλείου \eng{keil} δεν τοποθετεί τον \eng{SP} στο τέλος της μνήμης.
Για την ακρίβεια, χρησιμοποιώντας δύο τιμές από το \eng{configuration} του \eng{startup} αρχείου για το μέγεθος του σωρού και της στοίβας, υπολογίζει τη τιμή \eng{\textit{\textbf{\_\_initial\_sp}}.}
Αυτή την τιμή χρησιμοποιεί έπειτα σαν πρώτο όρισμα στο \eng{vector table} και άρα αυτή την τιμή έχει ο \eng{SP} κατά την εκκίνηση.

\par Έχοντας αυτό σαν δεδομένο μπορούμε να επιλέξουμε μια τιμή στην ελεύθερη περιοχή, έχοντας πάντα στο μυαλό μας ότι αλλάζοντας τα δεδομένα του προγράμματος η τιμή αυτή μπορεί να αλλάξει.
Στη δική μας περίπτωση η επιλεγμένη τιμή ήταν το \eng{\textbf{0x20001000}.}
Φυσικά αυτή η τιμή μπορεί να αλλάξει εύκολα αλλάζοντας απλώς την τιμή από το \eng{\textbf{\#define RESULT}.}
Μάλιστα αυτό είναι και κάτι που προτρέπουμε κάνει ο οποιονδήποτε θέλει να τρέξει τον κώδικά μας, ώστε να βεβαιωθεί πως η τιμή αυτή είναι στην ασφαλή ζώνη.


\section{Έλεγχος}
Για τον έλεγχο της ορθότητας του κώδικα χρησιμοποιήσαμε τον \eng{debuger} του εργαλείου κάνοντας ταυτόχρονη χρήση του \eng{simulator.}
Καθώς η εκφώνηση ανέφερε την δημιουργία μιας \eng{main,} θεωρήσαμε ότι είναι ευκαιρία να χρησιμοποιήσουμε την \eng{main} για να επιτύχουμε ένα είδους \eng{debug-mode unit testing.}
Έτσι στο εσωτερικό της δηλώσαμε αλφαριθμητικά για έλεγχο και για αυτά καλέσαμε την \eng{\textit{isPalindrome()}.}
Έπειτα εκτελώντας τον \eng{debuger} καταφέραμε να κάνουμε την όποια αποσφαλμάτωση που χρειάστηκε.

\section{Επίλογος}
Θεωρούμε ότι η παρούσα εργασία ήταν μια καλή πρώτη επαφή με την μίξη κώδικα \eng{C - assemblly,} καθώς και των όποιων απαιτήσεων από μεριάς \eng{assemblly} ώστε αυτή να είναι συμβατή με το πρότυπο που ακολουθεί ο \eng{compiler (AAPCS).}
Η μόνη παραφωνία σε αυτή τη συνεργασία ήταν η επιλογή μιας ελεύθερης θέσης μνήμης για την επιστροφή του αποτελέσματος.
Αυτό γιατί μέχρι τη σύνταξη του παρόντος δεν βρήκαμε τρόπο να διαβάσουμε από διαφορετικό αρχείο(πχ το \eng{main.c}) την τιμή \eng{\_\_initial\_sp,} ώστε η επιλογή της θέσης να αυτοματοποιηθεί.

% References
% ============================
%\begin{thebibliography}{100}
%    
%\bibitem{item}item...

%\end{thebibliography}

\end{document}