[assembler] Dostęp do danych

0

Witam,
to znowu ja i znów problem z assemblerem :)
Otóż, mam taki kawałek kodu :

movl	12(%ebp), %eax
cmpb	$'-', (%eax)		## (%eax) oznacza tak naprawde 0(%eax), czyli pierwszy bajt
jne	uzycie

dodam tylko, że po wykonaniu pierwszej z przedstawionych instrukcji, w EAX znajduje się adres (wskaznik po prostu) do stringa, w tym przypadku do pierwszego realnego (pomijając nazwę programu) parametru wywołania programu.
Korzystając z http://download.savannah.gnu.org/releases-noredirect/pgubook/ProgrammingGroundUp-1-0-booksize.pdf postanowiłem przetestować inny, teoretycznie równoważny, sposób dostępu do danych, mianowicie :

movl	12(%ebp), %eax
mov	%eax, adres
xor	%edi, %edi
mov	adres(, %edi, 1), %ebx
cmpb	$'-', %ebx
jne	uzycie

po takiej zamianie jednak, program działa inaczej, czyli znów (vide : mój poprzedni post) nie sprawdza, czy pierwszym znakiem pierwszego parametru jest '-' (myslnik).
Sprawdzałem gdb i w zmiennej "adres" rzeczywiście przechowywany jest ten sam adres, co w EAX. Jednakże, w EBX, zamiast oczekiwanej wartości 45 (kod ASCII myślnika) otrzymuję wartość 91 i nie mam pojęcia, dlaczego tak się dzieje.
Oczywiście, wiem, że mógłbym stosować po prostu ten sposób, który działa, jednak chciałbym zrozumieć wreszcie sposoby adresowania i stąd ten przykład.
Ponownie zwracam się z prośbą i pytaniem : czy wie ktoś może, dlaczego teraz nie działa ?

Zbychu

0

Ebx to rejestr 32bit, coś jak zmienna int, najniższa jednobajtowa część rejestru ebx to bl, naucz Ty się najpierw budowy rejestrów oraz rozmiarów danych, co?

Poza tym użyty sposób adresowania adresuje pamięć na 'adres', czytając ją bezpośrednio - 'adres' jest tą tablicą, którą indeksujesz, Ty próbujesz wczytać część adresu, nie stringa. Może gdybyś nie używał tego śmiesznego AT&T to prędzej byś załapał, napisałeś:

xor        %edi, %edi
mov        adres(, %edi, 1), %ebx

Co oznacza odczytaj do ebx (tak, do rejestru 32bit, nie pojedynczy znak a całą grupę!) wartość pod adresem [edi*1+666] (gdzie 666 jest pozycją zmiennej adres w pamięci). Żeby odczytać coś co jest pod adresem będącym wartością zmiennej 'adres' musisz ten adres najpierw do rejestru załadować. Po ludzku, całość przed przecinkiem to tylko kilka rejestrów i liczb (tak, to 'adres' przed nawiasem jest traktowane jako liczba, bo w końcu adres zmiennej jest liczbą), które są zliczane i ich wynik jest używany jako adres do odczytania danych, czego oczywiście w AT&T na pierwszy rzut oka nie widać... W takim wypadku zwyczajnie nie ma sensu tego rodzaju adresowania stosować, dopiero jak się poczujesz wystarczająco pewnie to zaczniesz się bawić tablicami, do tego to właśnie powstało.

Generalnie byłoby cacy gdybyś zrobił:

movl       12(%ebp), %eax
xorl       %edi, %edi
movb       0(%eax, %edi, 1), %bl # procesor jest w stanie tylko jedną dereferencję wykonać.
cmpb       $'-', %bl
jne        uzycie

No ale to totalnie zbędny, nadmiarowy kod.

Weź przejdź na Fasma albo jakiś inny assembler z sensowną składnią i ściągnij manuale Intela.

0

Witam,
dziękuję za odpowiedź, przeczytam jeszcze raz jutro na spokojnie.

Co do składni, to jest mi ona narzucona (muszę napisać programy zaliczeniowe) i stąd też nie bardzo mam możliwość ją zmienić.

Jeśli chodzi o rozmiary rejestrów, to mam świadomość, że (bynajmniej, u mnie) są one 4-bajtowe, a suffixów używam rzadko, bo z tego, co czytałem w manualu, GAS automatycznie dopasowywuje odpowiedni (w sensie : np. czy movl czy movb, itp.) suffix po rozmiarze rejestru (wyświetla tylko warningi). Oczywiście, przy porównaniach ma to znaczenie, co wcześniej pisałeś.

Generalnie to trochę się bawię GASem bo usiłuję zrozumieć jak działa i stąd te testy itp.
Jestem Ci bardzo wdzięczy za odpowiedź, ponownie zresztą.

Zbychu

0

Tak, sufiksy wymuszają zmianę rozmiaru rejestru... ale spróbuj odwołać się w ten sposób do ah/ch/dh/bh. Poza tym użycie sufiksów i pisanie rejestrów 32bit zdecydowanie zmniejsza czytelność.

Poza tym nie stosujesz sufiksów zbyt konsekwentnie - wyobraź sobie co się stanie jak sufiksu zapomnisz i dalej będziesz pełnych rejestrów używał przy operacjach na mniejszych typach danych. Tak, kompilator zastosuje jasno wskazany rejestr 32bit zamiast rzucić błędem. Szczególnie, że (g)as jest zwyczajnie głupi.

0
Świętowit napisał(a)

Poza tym użycie sufiksów i pisanie rejestrów 32bit zdecydowanie zmniejsza czytelność
Składnia AT&T jakoś specjalnie do czytelnych nie należy...
Jest niedorzeczna.

0

Co do składni, to jest mi ona narzucona (muszę napisać programy zaliczeniowe) i stąd też nie bardzo mam możliwość ją zmienić.

Składnia AT&T jakoś specjalnie do czytelnych nie należy...
Jest niedorzeczna.

Propozycja: Pisz w czymś normalnym a później deasembluj do AT&T ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1