EMAS: Różnice pomiędzy wersjami

Przejdź do nawigacji Przejdź do wyszukiwania
Dodane 13 339 bajtów ,  22 lut 2019
brak opisu edycji
Nie podano opisu zmian
Nie podano opisu zmian
(Nie pokazano 46 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 1: Linia 1:
EMAS jest assemblerem skrośnym dla MERRY 400, używającym, w odróżnieniu od [[ASSEM]], składni bliższej współczesnym assemblerom, oraz mnemoników MERY 400 (bez przyrostków zależnych od lokalizacji argumentu, patrz: [[Lista rozkazów]]).
EMAS jest assemblerem skrośnym dla komputera MERA 400, używającym (w odróżnieniu od [[ASSEM]]) składni bliższej współczesnym assemblerom, oraz mnemoników MERY 400 (ale bez przyrostków zależnych od lokalizacji argumentu, patrz: [[Lista rozkazów]]).
 
Repozytorium źródeł EMAS-a dostępne jest pod adresem: https://github.com/jakubfi/emas


= Wywołanie =
= Wywołanie =
Linia 5: Linia 7:
Wywołanie EMAS z linii poleceń ma postać:
Wywołanie EMAS z linii poleceń ma postać:


emas [opcje] [wejście [wyjście]]
emas [opcje] [wejście]


Gdzie:
Gdzie:


* '''wejście''' - nazwa wejściowego pliku źródłowego. Jeśli nie zostanie podana, EMAS czyta program ze standardowego wejścia, a wyjściem staje się plik ''out.bin''
* '''wejście''' - nazwa wejściowego pliku źródłowego. Jeśli nie zostanie podana, EMAS czyta program ze standardowego wejścia
* '''wyjście''' - nazwa wyjściowego pliku binarnego. Jeśli nie zostanie podana, przyjmowana jest nazwa ''out.bin''
* '''opcje''' - dowolne z:
* '''opcje''' - dowolne z:
** '''-O <otype>''' - typ wyniku asemblacji. Możliwe wybory to:
*** ''raw'' - binarny obraz gotowy do umieszczenia w pamięci maszyny i uruchomienia (domyślny wybór)
*** ''emelf'' - konsolidowalny obiekt [[EMELF]]
*** ''debug'' - tekstowy opis zawartości kolejnych komórek pamięci
*** ''keys'' - tekstowy opis zawartości kolejnych komórek pamięci w formacie łatwym do wprowadzenia z pulpitu technicznego maszyny
** '''-o <wyjście>''' - nazwa pliku wyjściowego. Jeśli nie zostanie podana, domyślny wygór zależy od typu wyniku asemblacji:
*** ''raw'' - nazwa pliku wejściowego z pominiętym rozszerzeniem. Jeśli wejście nie jest plikiem, to wyjściem jest plik 'a.out'
*** ''emelf'' - nazwa pliku wejściowego z rozszerzeniem zamienionym na '.o'. Jeśli wejście nie jest plikiem, to wyjściem jest plik 'a.out'
*** ''debug'' i ''keys'' - standardowe wyjście
** '''-c <cpu>''' - wybierz procesor, dla jakiego assembler produkuje binaria. Możliwe wybory to: ''mera400'', ''mx16''. Ustawienie procesora na MX-16 pozwala na użycie dodatkowych instrukcji oraz poszerza przestrzeń adresową programu z 32 do 64k słów. Domyślnie przyjmowany procesor to ''mera400''.
** '''-c <cpu>''' - wybierz procesor, dla jakiego assembler produkuje binaria. Możliwe wybory to: ''mera400'', ''mx16''. Ustawienie procesora na MX-16 pozwala na użycie dodatkowych instrukcji oraz poszerza przestrzeń adresową programu z 32 do 64k słów. Domyślnie przyjmowany procesor to ''mera400''.
** '''-O <otype>''' - wybierz typ pliku wyjściowego. Możliwe wybory to:
*** ''raw'' - binarny obraz gotowy do umieszczenia w pamięci i uruchomienia (domyślny wybór)
*** ''debug'' - plik tekstowy opisujący zawartość kolejnych komórek pamięci (przydatny w przypadku programowania komputera z pulpitu technicznego)
*** ''emelf'' - obiekt dla konsolidatora (opcja nie zaimplementowana)
** '''-I <katalog>''' - dodaj katalog do listy katalogów, w których poszukiwane będą pliki dołączane dyrektywą .include
** '''-I <katalog>''' - dodaj katalog do listy katalogów, w których poszukiwane będą pliki dołączane dyrektywą .include
** '''-D <stała>[=wartość]''' - zdefiniuj stałą i opcjonalnie nadaj jej wartość
** '''-v''' - wyświetl informacje o wersji i zakończ działanie
** '''-v''' - wyświetl informacje o wersji i zakończ działanie
** '''-h''' - wyświetl pomoc i zakończ działanie
** '''-h''' - wyświetl pomoc i zakończ działanie
** '''-d''' - drukuj informacje przydatne w śledzeniu błędów działania asemblera (dla deweloperów)
Oprócz katalogów podanych jako argumenty opcji '-I' EMAS używa następujących domyślnych katalogów, w których poszukuje plików dołączanych dyrektywą '''.include'''" (w kolejności):
* bieżący katalog
* /usr/share/emas/include
* /usr/local/share/emas/include
= Opis języka =
== Komentarze ==
EMAS pozwala na użycie komentarzy jedo- i wieloliniowych:
; samotny komentarz jednoliniowy
lw r1, 2 ; komentarz jednoliniowy na końcu dowolnej linii
/* komentarz
    wieloniniowy
*/
lw r1, 2 /* komentarz wieloliniowy, choć tak naprawdę w jedej linii */
/* można też tak */ lw r1, 2
== Stałe ==
Stałymi w programie mogą być liczby całkowite, liczby zmiennoprzecinkowe oraz łańcuchy znaków.
=== Liczby całkowite ===
Liczby całkowite można zapisywać w systemie binarnym, ósemkowym, dziesiętnym lub szesnastkowym, np:
0b1101110000
0177
-931
0xffa9
Istnieje jeszcze jeden sposób zapisu stałych całkowitoliczbowych, wynikający z ułożenia [[Rejestry i wskaźniki|wskaźników w rejestrze R0]], gdzie poszczególnym bitom przypisany jest jednoznakowy symbol ze zbioru (Z, M, V, C, L, E, G, Y, X, 1, 2, 3, 4, 5, 6, 7). Można dzięki niemu zapisać liczbę szesnastobitową z ustawionymi na 1 bitami, które odpowiadają danym wskaźnikom. Przykłady takiego zapisu stałych:
?ZM125
?GVZ
Wewnętrznie EMAS operuje na 32-bit liczbach ze znakiem. Kiedy ostateczna wartość będąca wynikiem operacji ma zostać umieszczona w obiekcie wynikowym, jej zakres jest sprawdzany i użytkownik jest informowany o ewentualnym jego przekroczeniu. Wyjątkiem jest argument dyrektywy '''.dword''', który jest 32-bit liczbą w kodzie U2.
=== Znaki ===
EMAS pozwala na zapisywanie stałych całkowitoliczbowych również przy pomocy znaków, dwuznaków lub trójznaków. Znaki pojedyncze oraz dwuznaki obejmują cały zakres znaków ASCII i można je podawać również używając sekwencji unikowych. Trójznaki pozwalają kodować jedynie znaki poprawne dla [[CROOK-5 - Interpretator zleceń użytkownika - XOSL#Kod R40|kodu R40]].
Znaki w pojedynczych cudzysłowach:
'a', '\n', '\xa1', '\0177'
kodowane są jako ich wartość w kodzie ASCII na młodszym bajcie słowa. Dwuznaki:
'ab', '\r\n', '\xaa\0001'
kodowane są jako wartości podanych znaków w kodzie ASCII odpowiednio na starszym i młodszym bajcie słowa.
=== Liczby zmiennoprzecinkowe ===
Akceptowane są następujące sposoby zapisu liczb zmiennoprzecinkowych:
9
1.2
0.003
-9.125e-2
1e4
Jedynym miejscem w programie, w którym może wystąpić liczba zmiennoprzecinkowa, jest argument dyrektywy '''.float'''.
=== Łańcuchy ===
Łańcuchy znaków są ciągami znaków ujętymi w podwójne cudzysłowy. Poszczególne znaki można zapisywać dosłownie, lub (w przypadku dyrektyw '''.ascii''' i '''.asciiz''') używając jednej z sekwencji unikowych:
* \0'''yyy''' - gdzie '''yyy''' jest ósemkowym kodem znaku
* \x'''yy''' - gdzie '''yy''' jest szesnastkowym kodem znaku
* \'''y''' - umożliwia zakodowanie jednego znaków specjalnych (wartości '''y''' inne niż poniżej są niepoprwane):
** \n - nowa linia
** \t - tabulacja pozioma
** \r - powrót karetki
** \f - wysuw strony
** \\ - dosłowny ukośnik w tył
** \" - dosłowny podwójny cudzysłów
Przykłady poprawnych łańcuchów znaków:
"MERA-400\n"
"\xab\xac\xad"
"\"napis\""
To, w jaki sposób znaki umieszczane są w programie wynikowym zależy od dyrektywy, której łańcuch jest argumentem.
=== Bieżąca lokalizacja ===
Specjalną stałą jest "." (kropka), która w danym miejscu programu zawsze zwraca przesunięcie względem początku assemblowanego obiektu. Jej wartość jest zawsze >= 0.
== Symbole ==
Symbolem jest ciąg znaków zaczynający się od małej lub dużej litery, z następującą dowolną ilością małych lub dużych liter, liczb lub znaku podkreślenia.
Symbolowi przypisywana jest w trakcie asemblacji wartość oraz atrybuty. Symbol może być:
* niezdefiniowany - wystąpiła deklaracja symbolu, ale nie został on (jeszcze) zdefiniowany,
* lokalny lub globalny - widoczny tylko w granicach obiektu, w którym występuje, bądź również poza nim,
* zmienny lub stały - wartość symbolu może, bądź nie może ulec zmianie w trakcie asemblacji programu.
Symbol otrzymuje atrybuty zgodne z tym w jakim kontekście został zdefiniowany bądź zadeklarowany.
=== Zmienne assemblera ===
Zmienne assemblera nie mają swojej reprezentacji w wynikowym obiekcie, są wartościami dostępnymi w trakcie asemblacji programu, a definiuje się je dyrektywą '''.equ'''. Symbol, który jest zmienną assemblera jest zawsze zmienny. Przykłady zmiennych:
.equ a 10
.equ b a+2
=== Stałe assemblera ===
Stałe assemblera również nie mają swojej reprezentacji w wynikowym obiekcie, są wartościami dostępnymi w trakcie asemblacji programu, a definiuje się je dyrektywą '''.const'''. Symbol, który jest zmienną assemblera jest zawsze stały. Przykłady stałych:
.const a 10
.const b a+9
=== Etykiety ===
Etykieta opisuje pozycję względem początku obiektu (jest nią wartość licznika rozkazów w danym momencie asemblacji). Przykład definicji etykiety:
etykieta:
=== Zasięg symboli ===
EMAS pozwala na zawężenie zasięgu symbolu przez poprzedzenie go kropką. Tak zdefiniowany symbol dostępny jest w zakresie od poprzedniego do następnego symbolu globalnego. Dzięki temu możliwe jest używanie takich samych nazw etykiet lokalnych w różnych kontekstach. Na przykład:
globalny1:
...
.lokalny:
...
ujs lokalny
globalny2:
.lokalny:
...
ujs lokalny
Skok 'ujs' wykonany zostanie każdorazowo do adresu opisanego symbolem ".lokalny", różnego dla zasięgów "globalny1" i "globalny2". Symbol lokalny nie może być zdefiniowany, jeśli uprzednio nie wystąpił żaden symbol globalny.
Można również odwołać się do lokalnego symbolu spoza jego zasięgu poprzedzając jego nazwę nazwą symbolu globalnego, w kontekście którego został zdefiniowany:
globalny1.lokalny
globalny2.lokalny
Lokalnych symboli można używać również definiując stałe i zmienne:
zmienna:
.equ a 1
.equ b 2
i odwoływać się do nich:
lw r1, zmienna.a
lw r2, zmienna.b
=== Widoczność symboli dla konsolidatora ===
Wszystkie symbole definiowane są jako widoczne wyłącznie w ramach asemblowanego obiektu. Jeśli symbol ma być widoczny dla konsolidatora, należy go zadeklarować jako zewnętrzny dyrektywą '''.global'''. Zmiana zasięgu może nastąpić przed, lub po definicji:
.global printf
.global snprintf
.global strdup
printf:
...
snprintf:
...
strdup:
procedura:
.global procedura
== Wyrażenia ==
=== Operatory ===
Poniższa tabela przedstawia operatory arytmetyczne i bitowe, w kolejności malejących priorytetów
{| class="wikitable"
! Operatory !! Działanie
|-
| ~ || negacja bitowa
|-
| \ || skalowanie
|-
| *, /, % || mnożenie, dzielenie, reszta z dzielenia
|-
| +, - || dodawanie, odejmowanie
|-
| <<, >> || przesunięcie bitowe w lewo i w prawo
|-
| &, <nowiki>|</nowiki>, ^ || logiczny iloczyn, suma i suma wykluczająca
|}
Operator skalowania realizuje funkcję dokładnie taką samą, jak przesunięcie bitowe, jest tylko innym sposobem jego zapisu. Poniższe zapisy są równoznaczne:
3\7  =  3 << (15-7)
Skalowanie można rozumieć jako: "umieść liczbę 3 od 7 pozycji bitowej w górę. Bity dla tego zapisu numerowane są od 0 (bit najstarszy) do 15 (bit najmłodszy). Wynikiem będzie więc liczba:
0000001100000000
== Dyrektywy assemblera ==
=== .cpu ===
'''Składnia:''' .cpu <mera400|mx16>
Odpowiednik przełącznika ''-c'' linii poleceń EMAS-a. Pozwala określić typ procesora, dla którego ma być generowany kod wynikowy. Użycie ''mx16'' sprawia, że:
* mnemoniki '''CRON''', '''SINT''', '''SIND''' są rozpoznawane i poprawnie assemblowane
* maksymalny rozmiar wynikowego pliku binarnego wynosi 64k słowa (32k dla ''mera400'')
=== .file ===
'''Składnia:''' .file ''nazwa_pliku''
Ustala nazwę assemblowanego pliku. Jeśli assembler będzie chciał użyć w komunikatach nazwy pliku, to domyślna nazwa (zgodna z nazwą assemblowanego pliku) zostanie od momentu wydania dyrektywy zastąpiona podaną.
=== .line ===
'''Składnia:''' .line ''numer_linii''
Ustala numer bieżącej linii assemblacji (poczynając od linii następującej po dyrektywie). Dalsze linie będą numerowane kolejno od podanej wartości.
=== .include ===
'''Składnia:''' .include ''nazwa_pliku''
Powoduje dołączenie do assemblacji pliku o podanej nazwie.
=== .equ ===
'''Składnia:''' .equ ''nazwa_zmiennej'' ''wartość''
Ustala wartość zmiennej assemblacji. Może być ona w dalszej części programu zmieniana.
=== .const ===
'''Składnia:''' .const ''nazwa_zmiennej'' ''wartość''
Ustala wartość stałej assemblacji. Wartość ta nie może ulec zmianie.
Zapisuje w programie wynikowym na prawych pozycjach (LSB) kolejnych słów podane wartośći 8-bit.
=== .word ===
'''Składnia:''' .word ''liczba_16_bit'' [, ...]
Zapisuje w programie kolejne słowa 16-bit o podanej wartości.
=== .dword ===
'''Składnia:''' .dword ''liczba_32_bit'' [, ...]
Zapisuje w programie wynikowym pary słów 16-bit tworzące podaną liczbę 32-bit.
=== .float ===
'''Składnia:''' .float ''liczba_zmiennoprzecinkowa'' [, ...]
Zapisuje w programie wynikowym trójki słów 16-bit tworzące podaną 48-bit liczbę zmiennoprzecinkową w notacji używanej przez arytmometr wielokrotnej precyzji MERY-400.
=== .ascii ===
'''Składnia:''' .ascii ''łańcuch''
Zapisuje w programie wynikowym podany łańcuch, kodując go po dwa znaki ASCII na słowo maszynowe.
=== .asciiz ===
'''Składnia:''' .asciiz ''łańcuch''
Zapisuje w programie wynikowym podany łańcuch, kodując go po dwa znaki ASCII na słowo maszynowe. Łańcuch terminowany jest 8-bit wartością '0'.
=== .res ===
'''Składnia:''' .res ''rozmiar'' [,''liczba_16_bit'']
Rezerwuje w programie wynikowym obszar o podanym rozmiarze (w słowach), wypełniając go zerami. Jeśli podany jest drugi argument, jego wartość używana jest do wypełnienia zamiast zera.
=== .org ===
'''Składnia:''' .org ''adres''
Ustala nową bieżącą pozycję assemblacji. Następne wygenerowane słowo zostanie umieszczone już pod podanym, nowym adresem.
=== .entry ===
'''Składnia:''' .entry ''adres''
Dyrektywa ma efekt wyłącznie w przypadku generowania pliku wynikowego jako obiektu EMELF. Określa adres wejścia do programu.
=== .global ===
'''Składnia:''' .global ''nazwa_etykiety''
Dyrektywa ma efekt wyłącznie w przypadku generowania pliku wynikowego jako obiektu EMELF. Wskazuje, że symbol będzie widoczny dla linkera.
=== .ifdef, .ifndef ===
Dyrektywa pozwala na asemblację warunkową podejmowaną istnieniem (bądź nie) zdefiniowanego symbolu.
.ifdef SYMBOL
... kod asemblowany, jeśl SYMBOL jest zdefiniowany ...
.else
... kod asemblowany, jeśli SYMBOL nie jest zdefiniowany ...
.endif
.ifndef SYMBOL
... kod asemblowany, jeśli SYMBOL nie jest zdefiniwoany
.endif
Symbol określający warunek może być zarówno etykietą, stałą lub zmienną zdefiniowaną w pliku źródłowym, jak również stałą zdefiniowaną podczas wywołania emas-a z opcją '-D'
=== .struct ===
Dyrektywa ta pozwala na stworzenie opisu struktury danych w celu uczynienia kodu źródłowego bardziej czytelnym. Nie formalizuje ona struktury, a jedynie ułatwia pracę z danymi. Przykład opisu struktury 'struktura':
.struct struktura:
    adres .res 1
    dluga_liczba .res 2
    tekst .res 64
.endstruct
Kolejne pozycje nazywają kolejne pola struktury i określają ich długość w słowach. Po asemblacji symbolom o tych nazwach przypisany zostanie offset w strukturze, a nazwie struktury - jej długość.
Użycie struktury w programie może wyglądać następująco:
moja_str: .res struktura
lw r3, moja_str
ld r3 + dluga_liczba
lw r7, moja_str + tekst
Definicja struktury z powyższego przykładu równoważna jest de facto następującemu ciągowi dyrektyw:
.const adres 0        ; offset pola 'adres'
.const dluga_liczba 1  ; offset pola 'dluga_liczba'
.const tekst 3        ; offset pola 'tekst'
.const struktura 67    ; rozmiar struktury 'struktura'
W strukturach można również zawęzić zakres nazewnictwa pól:
.struct struktura:
    .adres .res 1
    .dluga_liczba .res 2
    .tekst .res 64
.endstruct
Wtedy nazwy pól będą dostępne wyłącznie w kontekście danej struktury, a jej użycie wyglądać będzie następująco:
moja_str: .res struktura
lw r3, moja_str
ld r3 + struktura.dluga_liczba
lw r7, moja_str + struktura.tekst
== Rozkazy ==
Patrz: [[Lista rozkazów]].

Menu nawigacyjne