Jak przenieść projekt ze środowiska IAR Embedded Workbench do Atollic TrueSTUDIO – poradnik migracyjny

Celem jest wygenerowanie kodu rozpoczynającego i zamykającego wywołanie funkcji właściwego dla GCC i ciała funkcji pozwalającego na wywołanie funkcji bibliotecznej przenoszonej ze środowiska IAR.

Komendy służące do generowania kodu asemblerowego dla obu kompilatorów wyglądają następująco:

Spowodują one utworzenie plików wrapper_g.s oraz wrapper_i.s, które zawierają kod asemblerowy wygenerowany ze skompilowanego kodu źródłowego. Przyglądając się obu plikom można zauważyć części kodu odpowiadające za rozpoczynanie i kończenie procesu wywoływania funkcji, czyli ustawianie ramki stosu, obsługę przychodzących parametrów i wartości zwracanej oraz fragmenty odpowiadające za samo wywołanie funkcji foo.

UWAGA

Jak zostało zaznaczone wcześniej, standard wywoływania procedur określa, że jeśli wartość zwracana jest typu złożonego (struktura), o rozmiarze większym niż 4 bajty, używany jest dodatkowy argument określający lokalizację, w której wartość ta ma być zapisana. Rejestr r0 jest więc w takim przypadku używany do przechowania adresu w pamięci, pod którym zapisana zostanie wartość zwracana. Dla kodu wygenerowanego w środowisku IAR, pamięć jest zlokalizowana na szczycie stosu, natomiast dla kodu wygenerowanego w GNU – z 8-bajtowym offsetem w stosunku do początku stosu.

Na rys. 24 pokazano, jak wygenerowany kod można podzielić i połączyć w nową funkcję. W tym prostym przykładzie, jako że oba kompilatory są zgodne ze standardem wywoływania procedur, nie ma konieczności tworzenia pliku wrappera, można jednak zobaczyć jak wygląda opisywany mechanizm. Kod rozpoczynający i kończący wywołanie funkcji jest zaznaczony na niebiesko, kod ciała funkcji na zielono, a obsługa wartości zwracanej na czerwono.

 

Rys. 24.

Rys. 24.

 

 

Jako że funkcja wynikowa ma być wywoływana przez kod wygenerowany przez GCC, fragment kodu odpowiadający za rozpoczęcie i zakończenie wywoływania muszą pochodzić z kodu asemblerowego otrzymanego z GCC. Kod odpowiadający ciału funkcji należy z kolei skopiować z kodu asemblera otrzymanego za pomocą IAR EmbeddedWorkbench, co zapewnia że funkcja ma prawidłowo ustawione parametry.

UWAGA

Należy zwrócić uwagę na to, że jeśli lokalizacja danych wejściowych jest różna dla obu kompilatorów, część kodu odpowiadająca za obsługę parametrów wejściowych będzie różna w plikach z kodem asemblerowym. W takich przypadkach, kod zaznaczony na zielono musiałby przekształcać przekazywane parametry z części kodu odpowiadającej za rozpoczęcie wywołania na format wymagany przez znajdującą się „pod spodem” funkcję.

Kod odpowiadający ciału funkcji musi zostać zmodyfikowany, aby odzwierciedlać lokalizacje, w których przekazywane do funkcji parametry były przechowywane przez kompilator GNU. Można jednak zaobserwować, że parametry przekazywane do funkcji pozostają w rejestrach r1 i r2, więc zmodyfikowany kod ze środowiska IAR nie jest tak naprawdę potrzebny. Ostatnią sprawą, o którą trzeba zadbać jest, aby parametr przechowywany w r0 wskazywał na pamięć, która została zarezerwowana przez kompilator GNU na wartość zwracaną. Kod wynikający z połączenia został więc zmodyfikowany tak, by wykorzystywać rejestr r3 zamiast wskaźnika stosu.

Mając przygotowany plik wynikowy, można go włączyć jako kod źródłowy asemblera do projektu i zbudować całość.

Opracowanie wykonane na podstawie dokumentacji firmy Atollic: IAR Embedded Workbench to Atollic TrueSTUDIO migration guide; styczeń 2011.

O autorze