Thread View: pl.comp.lang.asm
8 messages
8 total messages
Started by Doleś
Fri, 11 Apr 2008 01:48
Transpozycja tablicy w C & Asembler
Author: Doleś
Date: Fri, 11 Apr 2008 01:48
Date: Fri, 11 Apr 2008 01:48
31 lines
2907 bytes
2907 bytes
Witam, mam pewien problem z transpozycją tablicy w Asemblerze. Napisałem wszystko oprócz samej transpozycji w C. Ten sam program pod Windowsem napisany w Visual Studio działa, ale pod Linuksem już nie chce. Naturalnie nie próbuję składni MASMa przerzucić na Linuksa :) Przepisałem sobie program na wg składni NASMa i oczywiście po kompilacji i asemblacji oraz linkowaniu mam legendarny, kochany błąd "Segmentation Fault". Próbowałem poradzić sobie samemu w związku z czym zrobiłem przyspieszony kurs obsługi GDB (którego jeszcze do dzisiaj nie potrafiłem obsługiwać) i debugowałem program. Zrobiłem "jump transponuj" i dawałem na przemian "stepi", "print /d $rejestr" oraz "x /10i <adres>" i starałem się kontrolować po kawałku jak się wykonuje program. O dziwo sam algorytm wydawał się poprawny, śledziłem zmienne no i nie było naruszenia ochrony pamięci w pętlach kodu. Problem powstał dopiero po instrukcji RET gdy kod programu poszedł sobie hen, hen daleko poza wstawkę w Asemblerze. Jedyne moje skojarzenie było takie, że gdzieś jest nadpisane EIP, ale analizowałem kod i nie mam pojęcia gdzie. Poza tym, czy gdyby nie było naruszenia stosu to nie wywaliłby komunikat "Smashing stack detectet" ? Bo kiedyś takie coś miałem jak próbowałem techniki przepełnienia bufora na własnym programie.Podejrzewam, że pewnie coś sknociłem przy przepisywaniu ze składni MASMa. Oto i kody źródowe wraz z Makefile. Kod w C: http://paste.org/index.php?id=2580 Kod w Asemblerze: http://paste.org/index.php?id=2581 Makefile: http://paste.org/index.php?id=2582 PS: Wybaczcie mi, że kod w Asemblerze jest taki "prostacki". Chciałem użyć adresowania do tablicy dwuwymiarowej wg schematu Tablica[x][y] = [Tablica + (x*dlugosc wiersza + y * rozmiar] ale nie mam takiej wprawy przy wielowymiarowych tablicach i brakowalo mi po prostu rejestrów na zrealizowanie takiego pomysłu a nie miałem żadnej idei kiedy okładać sobie coś na stos i z niego zdejmować.
Re: Transpozycja tablicy w C & Asembler
Author: Bogdan (bogdro)
Date: Fri, 11 Apr 2008 15:41
Date: Fri, 11 Apr 2008 15:41
41 lines
2842 bytes
2842 bytes
Doleś pisze: > Witam, > mam pewien problem z transpozycją tablicy w Asemblerze. Napisałem > wszystko oprócz samej transpozycji w C. Ten sam program pod Windowsem > napisany w Visual Studio działa, ale pod Linuksem już nie chce. > Naturalnie nie próbuję składni MASMa przerzucić na Linuksa :) > Przepisałem sobie program na wg składni NASMa i oczywiście po kompilacji > i asemblacji oraz linkowaniu mam legendarny, kochany błąd "Segmentation > Fault". Próbowałem poradzić sobie samemu w związku z czym zrobiłem > przyspieszony kurs obsługi GDB (którego jeszcze do dzisiaj nie > potrafiłem obsługiwać) i debugowałem program. Zrobiłem "jump transponuj" > i dawałem na przemian "stepi", "print /d $rejestr" oraz "x /10i <adres>" > i starałem się kontrolować po kawałku jak się wykonuje program. O dziwo > sam algorytm wydawał się poprawny, śledziłem zmienne no i nie było > naruszenia ochrony pamięci w pętlach kodu. Problem powstał dopiero po > instrukcji RET gdy kod programu poszedł sobie hen, hen daleko poza > wstawkę w Asemblerze. Jedyne moje skojarzenie było takie, że gdzieś jest > nadpisane EIP, ale analizowałem kod i nie mam pojęcia gdzie. Poza tym, > czy gdyby nie było naruszenia stosu to nie wywaliłby komunikat "Smashing > stack detectet" ? Bo kiedyś takie coś miałem jak próbowałem techniki > przepełnienia bufora na własnym programie. To mówi o tym, że adres powrotny jest nieprawidłowy. Nie musi być od razu zamazany. Pomyśl przez chwilę nad ostatnimi liniami kodu: pop ebp mov esp, ebp ret i w przyszłości używaj leave ret :) Ponoć szybsze, a i trudniej się pomylić. -- Pozdrawiam/Regards - Bogdan (GNU/Linux & FreeDOS) Kurs asemblera x86 (DOS, GNU/Linux):http://rudy.mif.pg.gda.pl/~bogdro Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32 www.JabberPL.org www.TorProject.org Soft (EN): miniurl.pl/bogdro-soft
Re: Transpozycja tablicy w C & Asembler
Author: Bernard
Date: Sat, 12 Apr 2008 12:35
Date: Sat, 12 Apr 2008 12:35
14 lines
1655 bytes
1655 bytes
Doleś wrote: > Witam, > mam pewien problem z transpozycją tablicy w Asemblerze. Napisałem > wszystko oprócz samej transpozycji w C. Ten sam program pod Windowsem > napisany w Visual Studio działa, ale pod Linuksem już nie chce. > Naturalnie nie próbuję składni MASMa przerzucić na Linuksa :) > Przepisałem sobie program na wg składni NASMa i oczywiście po kompilacji > i asemblacji oraz linkowaniu mam legendarny, kochany błąd "Segmentation > Fault". Próbowałem poradzić sobie samemu w związku z czym zrobiłem Zacznij od poprawienia błędu w epilogu - kolejność 2. i 3. instrukcji od końca. Ponadto prawdopodobnie kręcisz coś ze wskaźnikami - nietrudno o to przy tak zagmatwanym zapisie ich wyliczania i modyfikacji. Wyrzuć pushad i popad i wstaw to, co trzeba zgodnie z konwencją wołania.
Re: Transpozycja tablicy w C & Asembler
Author: doles2
Date: Sat, 12 Apr 2008 17:09
Date: Sat, 12 Apr 2008 17:09
53 lines
3613 bytes
3613 bytes
Bernard wrote:
>Zacznij od poprawienia błędu w epilogu - kolejność 2. i 3. instrukcji od
>końca. Ponadto prawdopodobnie kręcisz coś ze wskaźnikami - nietrudno o
>to przy tak zagmatwanym zapisie ich wyliczania i modyfikacji. Wyrzuć
>pushad i popad i wstaw to, co trzeba zgodnie z konwencją wołania.
Dzięki za pomoc. Faktycznie miałem skopane te rozkazy usuwające ramkę
stosu. Jednak to tylko wyeliminowało segmentation fault. Co gorsza
myślałem, że to koniec moich problemów ale oczywiście nie. Problem
polega na tym, że kombinowałem jak koń pod górkę aby napisać w
Asemblerze funkcję która robiłaby to samo co taki zapis w C:
for(i=0; i<A; i++)
for(j=0; j<B; j++)
transponowana[j][i] = macierz[i][j];
Czyli po prostu takie przepisanie wartości aby indeksy były
pozamieniane miejscami. Jak napisałem wcześniej chciałem użyć tego
schematu adresowania tablic dwuwymiarowych. Miałem pomysł aby
przypisać ESI np licznik "i", zaś dla EDI zmienną "j", jednak pomysł
spalił na panewce bo wg moich (zapewne błędnych) wyliczeń zabrakło po
prostu rejestrów ogólnego przeznaczenia. Potrzebuję dwóch rejestrów do
zachowania początków tablic, dwóch rejestrów na licznik pętli i kolumn
oraz jednego na bufor. Czyli aż chciało by się zapisać coś takiego:
mov esi, [ebp+ 8] ;adres macierzy źródłowej
mov edi, [ebp+12] ;adres macierzy docelowej
mov eax, [ebp+16] ;załaduj ECX na wartość liczby A
mov ebx, [ebp+20] ;załaduj EDX na wartość liczby B
imull eax,ebx
mov ecx,eax
petla:
mov edx, [esi + (eax*ebx + edi)*4]
mov [edi + (edi + (ebx*eax + esi)*4]
inc esi
inc edi
loop petla
;tutaj coś dalej sam nie wiem co
No ale takiego nienormalnego adresowania nie ma jak zapisałem a nawet
gdyby było, to w ten sposób dostałbym się tylko do elementów [0][0],
[1][1], [2][2] ... a co np z [0][1] ? Nie mam pojęcia. Użyłem takiego
głupiego kodu bo tylko tak pisząc to na kartce i robiąc próby
wychodziło mi teoretycznie dobranie się do wszystkich elementów obu
tablic. Jednak po uruchmieniu mam taki wynik:
0 1 2
3 4 5
------------------------------
196608 262144
327680 0
-1076123404 -1210122082
Wiem tylko tyle, że im bardziej się w to zagłębiam tym staję się
głupszy :(
Re: Transpozycja tablicy w C & Asembler
Author: Bogdan (bogdro)
Date: Sun, 13 Apr 2008 09:40
Date: Sun, 13 Apr 2008 09:40
72 lines
3467 bytes
3467 bytes
doles2@gmail.com pisze:
> Problem
> polega na tym, że kombinowałem jak koń pod górkę aby napisać w
> Asemblerze funkcję która robiłaby to samo co taki zapis w C:
> for(i=0; i<A; i++)
> for(j=0; j<B; j++)
> transponowana[j][i] = macierz[i][j];
>
> Czyli po prostu takie przepisanie wartości aby indeksy były
> pozamieniane miejscami. Jak napisałem wcześniej chciałem użyć tego
> schematu adresowania tablic dwuwymiarowych. Miałem pomysł aby
> przypisać ESI np licznik "i", zaś dla EDI zmienną "j", jednak pomysł
> spalił na panewce bo wg moich (zapewne błędnych) wyliczeń zabrakło po
> prostu rejestrów ogólnego przeznaczenia. Potrzebuję dwóch rejestrów do
> zachowania początków tablic, dwóch rejestrów na licznik pętli i kolumn
> oraz jednego na bufor. Czyli aż chciało by się zapisać coś takiego:
> mov esi, [ebp+ 8] ;adres macierzy źródłowej
> mov edi, [ebp+12] ;adres macierzy docelowej
> mov eax, [ebp+16] ;załaduj ECX na wartość liczby A
> mov ebx, [ebp+20] ;załaduj EDX na wartość liczby B
>
> imull eax,ebx
> mov ecx,eax
> petla:
> mov edx, [esi + (eax*ebx + edi)*4]
> mov [edi + (edi + (ebx*eax + esi)*4]
> inc esi
> inc edi
> loop petla
> ;tutaj coś dalej sam nie wiem co
> No ale takiego nienormalnego adresowania nie ma jak zapisałem a nawet
> gdyby było, to w ten sposób dostałbym się tylko do elementów [0][0],
> [1][1], [2][2] ... a co np z [0][1] ? Nie mam pojęcia.
Niech
int tab1[a][b];
int tab2[b][a];
Wtedy
tab1[i][j] = tab1[i*b+j] = [tab1+i*b+j];
tab2[j][i] = tab2[j*a+i] = [tab2+j*a+i];
W kodzie:
tab1 = esi
tab2 = edi
a = ecx
b = edx
for ( eax=0; eax < ecx; eax++ )
{
for ( ebx=0; ebx < edx; ebx++ )
{
push dword [esi+eax*edx+ebx];
pop dword [edi+ebx*ecx+eax];
}
}
Jak słusznie zauważyłeś, takie tryby adresowania nie istnieją,
trzeba więc te adresy poskładać:
EDX:EAX:=EAX*EDX
EAX:=EAX+EBX // EDX odrzucamy
push [esi+eax]
Podobnie drugi.
Jeszcze tylko pozostaje dopowiedzieć w razie czego, że warunek w
pętli for sprawdzany jest u góry i już masz gotowy algorytm.
--
Pozdrawiam/Regards - Bogdan (GNU/Linux & FreeDOS)
Kurs asemblera x86 (DOS, GNU/Linux):http://rudy.mif.pg.gda.pl/~bogdro
Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32
www.JabberPL.org www.TorProject.org Soft (EN): miniurl.pl/bogdro-soft
Re: Transpozycja tablicy w C & Asembler
Author: doles2
Date: Sun, 13 Apr 2008 20:01
Date: Sun, 13 Apr 2008 20:01
87 lines
4629 bytes
4629 bytes
On 13 Kwi, 11:40, "Bogdan (bogdro)" <bog...@poczta.gazeta.pl> wrote:
>
> Niech
> int tab1[a][b];
> int tab2[b][a];
>
> Wtedy
> tab1[i][j] = tab1[i*b+j] = [tab1+i*b+j];
> tab2[j][i] = tab2[j*a+i] = [tab2+j*a+i];
>
> W kodzie:
> tab1 = esi
> tab2 = edi
> a = ecx
> b = edx
>
> for ( eax=0; eax < ecx; eax++ )
> {
> for ( ebx=0; ebx < edx; ebx++ )
> {
> push dword [esi+eax*edx+ebx];
> pop dword [edi+ebx*ecx+eax];
> }
> }
Główkowałem się nieco nad tym i napisałem coś takiego:
global transponuj
section .text
transponuj:
push ebp
mov ebp, esp
mov esi, [ebp+8]
mov edi, [ebp+12]
mov ecx, [ebp+16]
mov edx, [ebp+20]
xor eax, eax
petla_wiersze:
cmp ecx, eax
je koniec
xor ebx,ebx
petla_kolumny:
cmp edx, ebx
je koniec_kolumn
mul edx
add eax, ebx
push [esi + eax]
imul ebx,ecx
add ebx,eax
pop [edi + ebx]
inc ebx
jmp petla_kolumny
koniec_kolumn:
inc eax
jmp petla_wiersze
koniec:
leave
ret
> Jak słusznie zauważyłeś, takie tryby adresowania nie istnieją,
> trzeba więc te adresy poskładać:
> EDX:EAX:=EAX*EDX
> EAX:=EAX+EBX // EDX odrzucamy
> push [esi+eax]
>
> Podobnie drugi.
Tutaj miałem niebotyczny problem, bo takie przeliczenie trzeba wykonać
przed "push dword [esi+eax*edx+ebx];" i przed "pop dword [edi+ebx*ecx
+eax];". Przed pierwszą operacją pobrania elementu z tablicy źródłowej
to tam pikuś, ale gorzej z drugą gdzie potrzebuję starych wartości EAX
i EBX z pętli a nie po obliczeniach. W związku z tym ja już sam
pisałem mało wiele podobny kod ale nie potrafiłem sobie poradzić
właśnie z przechowaniem wartości tych liczników :/ Nie wiem gdzie mam
zrobić PUSH i POP aby je jakoś zachować albo jest jeszcze inny sposób.
Liczyłem sobie na kartce to jeśli nie popełniłem błędu albo nie znam
jakiegoś triku, to niestety nie da się użyć policzonego EAX (tego dla
elementu macierzy źródłowej) w pobraniu elementu dla macierzy
docelowej. Co operację to trzeba liczyć od nowa :(
> Jeszcze tylko pozostaje dopowiedzieć w razie czego, że warunek w
> pętli for sprawdzany jest u góry i już masz gotowy algorytm.
Na początku nie wiedziałem o co Ci chodzi, ale potem załapałem. Trzeba
sprawdzać warunek u góry pętli bo jeśli np EAX dawno jest równe ECX to
wykona się cała pętla, kod dawno coś naknoci z macierzami a warunek
sprawdzę dopiero na końcu :)
Pewnie pisząc tę wiadomość już dość mocno nadużywam Twojej
cierpliwości i dobrych chęci, zatem z góry przepraszam :)
Re: Transpozycja tablicy w C & Asembler
Author: Jacek Wawrzaszek
Date: Sun, 13 Apr 2008 22:30
Date: Sun, 13 Apr 2008 22:30
29 lines
2090 bytes
2090 bytes
> myślałem, że to koniec moich problemów ale oczywiście nie. Problem
> polega na tym, że kombinowałem jak koń pod górkę aby napisać w
> Asemblerze funkcję która robiłaby to samo co taki zapis w C:
> for(i=0; i<A; i++)
> for(j=0; j<B; j++)
> transponowana[j][i] = macierz[i][j];
Powyższy algorytm można zapisać następująco (nota bene w ten właśnie
sposób powinien go zoptymalizować kompilator języka C):
int *pM = &macierz[0][0];
for(int i=0; i<A; i++)
{
int *pT = &transponowana[0][i];
for(int j=0; j<B; j++)
{
*pT = *(pM++);
pT += A;
}
}
Postać ta jest wygodniejsza do przekształcenia na assembler, a na dodatek
działa bardzo szybko, bo nie potrzebuje ani jednej operacji mnożenia.
"Na oko" wydaje mi się, że powyższy algorytm da się zaimplementować
przy użyciu 7 rejestrów, bez konieczności przechowywania czegokolwiek
na stosie (oczywiście poza parametrami wywołania funkcji).
J.
Re: Transpozycja tablicy w C & Asembler
Author: Bogdan (bogdro)
Date: Mon, 14 Apr 2008 15:42
Date: Mon, 14 Apr 2008 15:42
68 lines
3980 bytes
3980 bytes
doles2@gmail.com pisze: > Główkowałem się nieco nad tym i napisałem coś takiego: > global transponuj > section .text [...] No, nawet ładnie to wyszło. Nie wygląda, aby nie działało, ale spytam: działa? :) >> Jak słusznie zauważyłeś, takie tryby adresowania nie istnieją, >> trzeba więc te adresy poskładać: >> EDX:EAX:=EAX*EDX >> EAX:=EAX+EBX // EDX odrzucamy >> push [esi+eax] >> >> Podobnie drugi. > Tutaj miałem niebotyczny problem, bo takie przeliczenie trzeba wykonać > przed "push dword [esi+eax*edx+ebx];" i przed "pop dword [edi+ebx*ecx > +eax];". Przed pierwszą operacją pobrania elementu z tablicy źródłowej > to tam pikuś, ale gorzej z drugą gdzie potrzebuję starych wartości EAX > i EBX z pętli a nie po obliczeniach. W związku z tym ja już sam > pisałem mało wiele podobny kod ale nie potrafiłem sobie poradzić > właśnie z przechowaniem wartości tych liczników :/ Nie wiem gdzie mam > zrobić PUSH i POP aby je jakoś zachować albo jest jeszcze inny sposób. Można wyliczone wartości dodać do ESI/EDI, zwalniając rejestry: mul edx add eax, ebx add esi, eax ; tu EAX już wolny push dword [esi] imul ebx,ecx add ebx,eax add edi, ebx ; tu EBX wolny pop dword [edi] Można włożyć na stos, można zachować do zmiennej. "Dword"-y dorobiłem w razie czego. > Liczyłem sobie na kartce to jeśli nie popełniłem błędu albo nie znam > jakiegoś triku, to niestety nie da się użyć policzonego EAX (tego dla > elementu macierzy źródłowej) w pobraniu elementu dla macierzy > docelowej. Co operację to trzeba liczyć od nowa :( Trudno. Prosty algorytm nie musi oznaczać wydajny algorytm. Kolega Jacek podał ciekawy algorytm (ale także działający tylko dla tablic dwuwymiarowych, nie dla tablic wskaźników na wiersze). >> Jeszcze tylko pozostaje dopowiedzieć w razie czego, że warunek w >> pętli for sprawdzany jest u góry i już masz gotowy algorytm. > Na początku nie wiedziałem o co Ci chodzi, ale potem załapałem. Trzeba > sprawdzać warunek u góry pętli bo jeśli np EAX dawno jest równe ECX to > wykona się cała pętla, kod dawno coś naknoci z macierzami a warunek > sprawdzę dopiero na końcu :) Tak, właśnie o to chodziło :) > Pewnie pisząc tę wiadomość już dość mocno nadużywam Twojej > cierpliwości i dobrych chęci, zatem z góry przepraszam :) E, nie ma za co :) Grunt aby działało i abyś się nauczył czegoś nowego. Inni czytający też - ja też musiałem chwilkę pogłówkować :) -- Pozdrawiam/Regards - Bogdan (GNU/Linux & FreeDOS) Kurs asemblera x86 (DOS, GNU/Linux):http://rudy.mif.pg.gda.pl/~bogdro Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32 www.JabberPL.org www.TorProject.org Soft (EN): miniurl.pl/bogdro-soft
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads