Droga Przyjaciolko, zebra, odbicia
Maciej W. Rozycki
macro w ds2.pg.gda.pl
Wto, 1 Lut 2000, 17:11:25 MET
On Tue, 1 Feb 2000, Rafal Maszkowski wrote:
> Probowalem uruchomic zebre. Bardzo pomagal mi przy tym agaran, ale poniewaz
> wojboj podsunal pomysl rozwiazania problemow z mrtd, wiec nie pilowalem do
> konca. Problemy (Sparc/Linux) polegaja na aligningu. Nie wiem dlaczego binaria
> sparcowe sie sypia (Bus Error) jezeli np. siegamy do inta, ktory ma adres
> 0xNNNNNNf, czemu kompilator tego nie przerabia na kilka mov-ow 1-bajtowych.
Siegnijmy do zrodla -- dlaczego int nie jest wyrownany? Kompilator nie
ma zwyczaju generowac zmiennych niewyrownanych, chyba ze poda mu sie
upakowana strukture (tj. z klauzula __attribute__((packed))), a wtedy
stosuje sekwencje rozkazow zastepczych.
Nie znam SPARCa, ale przypuszczam, ze podobnie jak i inne procesory o
architekturze RISC, udostepnia on rozkazy typu "zaladuj dana niewyrownana
z lewej" i "zaladuj dana niewyrownana z prawej", ktore laduja w sposob
komplementarny lewa i prawa czesc rejestru (ilosc bitow ladowanych przez
kazdy z nich zalezy od wyrownania adresu). Para takich rozkazow wystarcza
do zaladowania niewyrownanego inta. Wymaga to jednak o 100% wiecej kodu i
czasu procesora, wiec normalnie sie tego rozwiazania nie stosuje, a w
zamian odpowiednio wyrownuje sie zmienne.
Przy zapisie sytuacja jest analogiczna.
> Ktos to rozumie? Nie umiem tego rozwiazac globalnie, chociaz -O0 jakby nieco
> pomagalo, wyglada, ze wymaga to dlugich godzin hackowania.
Pomaga, gdyz operacje typu memcpy() na blokach o stalych rozmiarach sa
przy wlaczonej optymalizacji kodowane przez gcc jako sekwencje rozkazow.
Np.:
memcpy((int *)dst, (int *)src, 4);
to beda typowo dwa rozkazy procesora ("zaladuj" i "zapisz"). Z drugiej
strony, wolanie:
memcpy((char *)dst, (char *)src, 4);
zostanie rozwiniete w dluzszy kod, uwzgledniajacy, ze zmienne typu char
moga miec dowolne wyrownanie, a nie tylko do wielokrotnosci 4, tak jak
int. Przy braku optymalizacji wolane beda funkcje biblioteczne, ktore
zawsze musza jawnie sprawdzac wyrownanie adresow i postepowac odpowiednio.
Kod, w ktorym wystepuja zmienne niewyrownane w kontekstach innych niz w
upakowanych strukturach jest przede wszystkim zle napisany. Tego rodzaju
objawy wystepuja np. przy nieostroznym rzutowaniu typow argumentow
funkcji. Sposob wyeliminowania tego problemow z wyrownaniem zalezy od
konstrukcji konkretnych fragmentow kodu.
Jednym ze sposobow na wyluskanie danych niewyrownanych, przydatnych np.
gdy mamy "wektor" danych o roznym rozmiarze (sytuacja spotykana np. przy
stosowaniu algorytmow kompresji danych) jest rzutowanie typu na upakowana
strukture. Np. w kontekscie nastepujacej definicji:
typedef struct { int v __attribute__((packed)); } int_s;
nastepujace wyrazenie zwroci poprawna wartosc zmiennej x typu int,
niezaleznie od jej wyrownania:
((int_s *)&(x))->v;
Powyzsza metoda dziala dla egcs w wersji 1.1 i nowszych (wlaczajac w to,
oczywiscie, gcc 2.95).
Oczywiscie, zamiast dlubac samodzielnie, mozna na to zwrocic uwage
(zapewne intelocentrycznemu) autorowi programu.
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro w ds2.pg.gda.pl, PGP key available +
Więcej informacji o liście dyskusyjnej 6BONE-PL