EMDAS

EMDAS jest deassemblerem binariów MERY 400. Jego wyjściem jest program assemblerowy w składni akceptowanej przez EMAS-a. EMDAS przeprowadza analizę kodu pozwalającą w prostych przypadkach na umieszczenie w wynikowym listingu etykiet, co ułatwia jego analizę.

Deassembler dostępny jest jako samodzielny program, oraz biblioteka.

Repozytorium źródeł EMDAS: https://github.com/jakubfi/emdas

Wywołanie

Wywołanie EMDAS z linii poleceń ma postać:

emdas [opcje] wejście

Gdzie:

  • wejście - nazwa wejściowego pliku binarnego
  • opcje - dowolne z:
    • -o wyjście - ustal nazwę wyjściowego pliku z listingiem. Jeśli nie zostanie podana, listing drukowany jest na standardowe wyjście.
    • -c cpu - użyj listy rozkazów wskazanego procesora (dostępne: mera400, mx16, domyślnie mera400)
    • -a <adres> - ustaw adres bazowy deasemblacji (domyślnie 0)
    • -l - użyj mnemoników pisanych małymi literami
    • -na - nie umieszczaj w listingu adresów
    • -nc - nie umieszczaj w listingu komentarzy z alternatywną deassemblacją
    • -nl - nie analizuj kodu i nie umieszczaj w listingu etykiet
    • -v - wyświetl informację o wersji i zakończ działanie
    • -h - wyświetl pomoc i zakończ działanie

Aby listing był programem poprawnym dla EMAS, należy wyłączyć drukowanie adresów. Przykładowe wywołanie dające taki wynik to:

emdas -na em400/boot/boot_winch.bin boot.asm

Biblioteka

Wraz z narzędziem wywoływanym z linii poleceń instalowana jest biblioteka dynamiczna libemdas.

Funkcje biblioteczne

struct emdas *emdas_create(int iset_type, emdas_getfun getfun)

Utwórz instancję deassemblera używającego listy rozkazów iset_type (EMD_ISET_MERA400 lub EMD_ISET_MX16) i funkcji getfun służącej do pobrania słowa z pamięci. Funkcja ma definicję: uint16_t * emdas_getfun(int nb, uint16_t addr). Jako argumenty przyjmuje numer bloku pamięci nb (0-15) i adres addr. Funkcja zwraca wskaźnik do instancji deassemblera lub NULL, jeśli nie udało się go utworzyć. W takim przypadku zmienna emdas_error zawiera przyczynę niepowodzenia.

void emdas_destroy(struct emdas *emd)

Usuń instancję deassemblera.

int emdas_set_features(struct emdas *emd, unsigned features)

Ustaw właściwości deassemblera na features, które zawierają sumę logiczną dowolnych z:
  • EMD_FEAT_NONE - brak właściwości
  • EMD_FEAT_ADDR - umieszczas adresy w listingu
  • EMD_FEAT_LMNEMO - używaj mnemoników pisanych małymi literami
  • EMD_FEAT_ALTS - załączaj komentarze z alternatywną deassemblacją
  • EMD_FEAT_IOARGS - traktuj cztery kolejne słowa za instrukcjami IN i OU jako ich argumenty
Funkcja zwraca EMD_E_OK w przypadku powodzenia, lub EMD_E_FEATURE_UNKNOWN w przypadku próby ustawienia nieznanej właściwości.

unsigned emdas_get_features(struct emdas *emd);

Pobierz właściwości deassemblera.

int emdas_set_tabs(struct emdas *emd, unsigned label, unsigned mnemo, unsigned arg, unsigned alt)

Ustaw tabulacje dla listingu. Każda linia deassemblacji rozpoczyna się od kolumny 0 i może składa się z pięciu elementów, z których dla czterech ostatnich można ustawić kolumnę początkową:
  • adres
  • etykieta
  • mnemonik
  • argumenty
  • komentarz z alternatywami
Funkcja zwraca EMD_E_OK w przypadku powodzenia, lub EMD_E_TABS_MISPLACED w przypadku próby ustawienia błędnych tabulacji.

void emdas_set_nl(struct emdas *emd, char c)

Ustaw znak kończący linię deassemblacji na c.

char * emdas_get_buf(struct emdas *emd);

Pobierz wskaźnik do bufora, w którym deassembler zapisuje wynik deassemblacji. Wskaźnik nie zmienia się w trakcie życia instancji deassemblera.

int emdas_analyze(struct emdas *emd, unsigned nb, uint16_t addr, unsigned size);

Przeprowadź analizę size słów pamięci w bloku nb, poczynając od adresu addr. Analiza ma na celu ustalenie etykiet na podstawie argumentów rozkazów. Będą one później użyte przy deassemblacji i drukowaniu listingu funkcją emdas_dasm.

int emdas_dasm(struct emdas *emd, unsigned nb, uint16_t addr);

Przeprowadź deassemblację jednej instrukcji poczynając od adresu addr w bloku pamięci nb. Funkcja zwraca wartość >=0 - ilość słów pamięci użytych w przypadku przeprowadzenia poprawnej deassemblacji, lub wartość ujemną wskazującą błąd.

int emdas_get_linecnt(struct emdas *emd);

Pobierz ilość linii listingu będących wynikiem ostatniego wywołania funkcji emdas_dasm.