Na początek trochę teorii o WinDLX.
Wikipedia podaje takie informacje:
WinDLX – symulator (asembler) architektury DLX pracujący pod kontrolą systemu Microsoft Windows.
~Wikipedia
Nie jest tego dużo. Ale czy więcej nam się przyda, żeby zaliczyć laboratoria? Nie. Tyle wystarczy :)
WinDLX posiada tzw. fazy wykonywania instrukcji, inaczej nazywane cyklami. W naszym programie wyglądają one następująco:
Każdy z nich oznacza daną fazę (cykl), który WinDLX aktualnie przetwarza. Oznaczają następująco:
IF - faza pobierania instrukcji,
ID - faza dekodowania instrukcji,
EX - faza wykonywania instrukcji,
MEM - faza dostępu do pamięci,
WB - faza, gdzie zapisuje się wynik operacji do rejestru.
Dodatkowo kolejne instrukcje (instrukcje składają się z kilku cykli), mogą być przetwarzane na dwa sposoby:
Przetwarzanie klasyczne instrukcji:
Charakteryzuje się tym, że dopóki nie zakończy się dana operacja, czyli dopóki przetwarzana wartość nie zostanie zapisana do rejestru, następna operacja, która np. potrzebuje tą wartość z rejestru, nie wykona się. Spowalnia to działanie napisanego programu, ale nie generuje błędów (o tym za chwilę).
Przetwarzanie potokowe instrukcji:
Charakteryzuje się tym, że dane instrukcje są wykonywane równolegle. Jednocześnie może być wykonywanych kilka cykli na raz. Stwarza to ryzyko, że wtedy instrukcja, potrzebuje dane z poprzedniej instrukcji, która jeszcze nie została wykonana. Nazywamy to wtedy hazardem przetwarzania potokowego.
Kolejne rozkazy nie pobierają potrzebnych danych bezpośrednio z rejestrów (co wykonuje się w fazie WB), tylko od razu biorą z konkretnej fazie. WinDLX pokazuje to, wstawiając do diagramu strzałeczkę:
Przetwarzanie potokowe jest dużo szybsze, w przeciwieństwie do przetwarzania klasycznego.
Rejestry
Dane, z których korzysta nasz program są zapisywane w rejestrach oraz w pamięci. Jest kilka rodzajów rejestrów i będziemy stosować różne z nich, w zależności od potrzeby:
- Rejestry ogólnego przeznaczenia
Są to rejestry od R0 do R31.
W najważniejsze rejestry, które mają z góry określoną własność, to:
R0 - zawsze zawiera wartość 0;
R31 - zawiera adres powrotu po wykonaniu skoku ze śladem
- Rejestry zmiennoprzecinkowe
Są to rejestry od F0 do F31. Wtedy są tam przechowywane liczby o pojedynczej precyzji.
Aby przetworzyć te rejestry, na rejestry o podwójnej precyzji, trzeba jest grupować parami, np:
(F0,F1), (F2,F3), itd. Zawsze wtedy, w przypadku podwójnej precyzji, zapisujemy do rejestru o parzystym indeksie.
- Rejestry specjalne
Są to rejestry różnego przeznaczenia. (Nazwy powinny być znajome z LabSag'a, nie będę tłumaczyć :) )
PC, IR, IAR, IMAR, DMAR, SDR, SDRHI, LDR, LDRH, A, AHI, B, BHI, ALU, ALUHI, BTA, FPSR.
Pamięć
Aby dostać się do pamięci, klikamy:I mamy w ten sposób podgląd do całej pamięci :)
Przydatny informacje, gdy chcemy pisać kod
Komentarze: piszemy ; i wszystko co po nim jest wykomentowaneEtykiety (cos jak zmienne): n:100, Tab: 1,2,3
Dyrektywy: .data, .text, .align, .global
Symbole rejestru: r1,f3,d4
Argumenty natychmiastowe: #33,x
Mnemoniki (nazwy rozkazów): addi, sub, mult
Typy danych:
.byte - bajt, np. .byte 900
.word - słowo, np. nw: .word 100
.float - zmienna typu float, np. nf: .float 3.0
.double - zmienna o podwójnej precyzji, np. nd: .double 1000
.asciiz - ciąg znaków, np. .asciiz "Napis"
.space - rezerwuje miejsce w pamięci, np. ns: .space 4
Rozkazy:
Rozkaz składa się z mnemonika oraz rejestrów lub argumentu natychmiastowego.
ADD r3, r0, r5
W pisaniu program przydatne też są rozkazy trap. Na początku interesować nas będą jedynie dwa:
trap 0 - kończy działanie programu, musi się znaleźć zawsze, na samym końcu.
trap 5 - będziemy go używać do wyświetlania wybranych przez nas elementów na domyślne wyjście.