Thread View: pl.comp.lang.asm
15 messages
15 total messages
Started by Kamil
Sun, 01 Sep 2013 20:00
Konwersja dużych liczb
Author: Kamil
Date: Sun, 01 Sep 2013 20:00
Date: Sun, 01 Sep 2013 20:00
6 lines
1217 bytes
1217 bytes
Witam Może ktoś ma pod ręką procedurę zamiany dużych liczb (przekraczających rejestry) hex na dec? Ewentualnie gdzie tego szukać? Pzdr
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Fri, 06 Sep 2013 17:24
Date: Fri, 06 Sep 2013 17:24
27 lines
2276 bytes
2276 bytes
W dniu 01.09.2013 22:00, Kamil pisze: > Witam > > Może ktoś ma pod ręką procedurę zamiany dużych liczb (przekraczających > rejestry) hex na dec? Ewentualnie gdzie tego szukać? > > Pzdr > Witam. Trochę nie rozumiem, przyznaję. Po wczytaniu do pamięci lub rejestru każda liczba jest w takiej postaci, jaką chcesz - możesz ją traktować jako szesnastkową, dziesiętną, dwójkową itd. Zapewne chodzi Ci o wczytanie liczby w postaci hex (czyli ze znaków 0-9, a-f, A-F), po czym o _wyświetlenie_ jej w formie dziesiętnej, tak? Potrzebujesz dzielenia wielokrotnej precyzji oraz wczytywania liczb hex. Wszystko na pewno znajdziesz w "Art of Assembly", a dodatkowo w mojej bibliotece (http://rudy.mif.pg.gda.pl/~bogdro/) i kursie, np. http://rudy.mif.pg.gda.pl/~bogdro/dos/a_kurs14.htm i http://rudy.mif.pg.gda.pl/~bogdro/dos/a_kurs17.htm. -- 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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Fri, 06 Sep 2013 21:33
Date: Fri, 06 Sep 2013 21:33
22 lines
2352 bytes
2352 bytes
Użytkownik "Bogdan (bogdro)" napisał: > Trochę nie rozumiem, przyznaję. Po wczytaniu do pamięci lub rejestru > każda liczba jest w takiej postaci, jaką chcesz - możesz ją traktować > jako szesnastkową, dziesiętną, dwójkową itd. Może podałem za mało danych. Chodzi o Windows i Masm32. Mam kalkulator, który ma np. dodawać liczby dec. Funkcja GetDlgItemText wczytuje liczby dec z kontrolki zamieniając je na ASCII. Jeśli mam w kontrolce 123, to po ich wczytaniu w buforze jest już 313233. Taka postać nie nadaje się do dalszych obliczeń. Trzeba "oczyścić" te dane z ASCII, czyli doprowadzić do postaci 123, a następnie zamienić na hex czyli 7B, bo tylko taka postać nadaje się do dalszych działań. Po wykonaniu dodawania trzeba wynik przekształcić na dec, czyli jeśli wynikiem dodawania będzie F6h to trzeba to przekonwertować na 246 i następnie zrobić z tego ASCII - 323436 i to dopiero podać na ekran. Podałem liczby przykładowe, króre nie stanowią problemu bo mieszczą się w rejestrach. Natomiast pod to rozumowanie podstawmy liczby np 128 bajtowe i przeprowadźmy po kolei te wszystkie potrzebne konwersje. Pozdrawiam
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Sat, 07 Sep 2013 16:55
Date: Sat, 07 Sep 2013 16:55
68 lines
4534 bytes
4534 bytes
W dniu 06.09.2013 23:33, Kamil pisze: > Użytkownik "Bogdan (bogdro)" napisał: > >> Trochę nie rozumiem, przyznaję. Po wczytaniu do pamięci lub rejestru >> każda liczba jest w takiej postaci, jaką chcesz - możesz ją traktować >> jako szesnastkową, dziesiętną, dwójkową itd. > > Może podałem za mało danych. Chodzi o Windows i Masm32. > > Mam kalkulator, który ma np. dodawać liczby dec. Funkcja > GetDlgItemText wczytuje liczby dec z kontrolki zamieniając je na > ASCII. Tak właściwie, to już są w ASCII. Funkcja po prostu umieszcza tekst w buforze, nie konwertuje sama sobie np. cyfry "1" na wartość 31h, bo to, co robi za cyfrę "1", już ma wartość 31h. > Jeśli mam w kontrolce 123, to po ich wczytaniu w buforze jest > już 313233. Taka postać nie nadaje się do dalszych obliczeń. Trzeba > "oczyścić" te dane z ASCII, czyli doprowadzić do postaci 123, a > następnie zamienić na hex czyli 7B, bo tylko taka postać nadaje się do > dalszych działań. Po wykonaniu dodawania trzeba wynik przekształcić na > dec, czyli jeśli wynikiem dodawania będzie F6h to trzeba to > przekonwertować na 246 i następnie zrobić z tego ASCII - 323436 i to > dopiero podać na ekran. Podałem liczby przykładowe, króre nie stanowią > problemu bo mieszczą się w rejestrach. Natomiast pod to rozumowanie > podstawmy liczby np 128 bajtowe i przeprowadźmy po kolei te wszystkie > potrzebne konwersje. Dobrze, to kroki powinny być takie: 1. Oczyszczanie z ASCII: iterujemy po jednym znaku na raz: a) wczytaj kolejny znak z bufora (od przodu) b) odejmij 30h (kod zera w ASCII) lub po prostu '0' czy "0" c) bieżącą liczbę pomnóż przez 10 (mnożenie wielokrotnej precyzji z mojej strony) d) do bieżącej liczby dodaj znak pomniejszony o 30h w punkcie b) - tu nie trzeba dodawania wielokrotnej precyzji 2. Zamieniać na hex w pamięci już nie musisz. Tak, jak pisałem, liczba otrzymana w punkcie 1 jest już w pamięci komputera (równocześnie w systemie binarnym, szesnastkowym dziesiętnym, ósemkowym czy jaki tam akurat trzeba). Bity to bity, a to, jak te dane potraktujesz, zależy tylko od Ciebie. Gdybyś, na przykład wykonał kroki z punktu 1 dla ciągu znaków "10", to w pamięci już po kroku pierwszym miałbyś 0A. 3. Mając tak przygotowane dane wejściowe, wykonujesz odpowiednie działanie (dodawanie, odejmowanie itp.). 4. Zamieniać na postać dziesiętną w pamięci nie musisz. 5. Konwersja na ASCII: najlepiej też metoda po jednym znaku na raz: a) wyczyść bufor podręczny i wyjściowy b) jeśli liczba jest zerem, to przejdź do g) c) dzielimy liczbę przez 10 (dzielenie wielokrotnej precyzji) d) do RESZTY z dzielenia dodajemy '0' (lub 30h) e) zmienioną resztę z dzielenia zapisujemy w buforze podręcznym f) wracamy do punktu a) g) w buforze wyjściowym zapisz reszty z dzielenia znajdujące się w buforze podręcznym, ale WSPAK (pierwszy bajt ma być ostatnim) h) wyświetl bufor wyjściowy -- 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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Sun, 08 Sep 2013 11:38
Date: Sun, 08 Sep 2013 11:38
50 lines
3281 bytes
3281 bytes
Użytkownik "Bogdan (bogdro)" napisał: >> GetDlgItemText wczytuje liczby dec z kontrolki zamieniając je na >> ASCII. > Tak właściwie, to już są w ASCII. Funkcja po prostu umieszcza tekst w > buforze, nie konwertuje sama sobie np. cyfry "1" na wartość 31h, bo > to, co robi za cyfrę "1", już ma wartość 31h. W kontrolce jest 1, a funkcja pobierając znak "w locie" go konwertuje i do bufora wpisuje już 31. Widziałem to w debuggerze. > Dobrze, to kroki powinny być takie: > 1. Oczyszczanie z ASCII: iterujemy po jednym znaku na raz: > a) wczytaj kolejny znak z bufora (od przodu) > b) odejmij 30h (kod zera w ASCII) lub po prostu '0' czy "0" > c) bieżącą liczbę pomnóż przez 10 (mnożenie wielokrotnej precyzji z > mojej strony) > d) do bieżącej liczby dodaj znak pomniejszony o 30h w punkcie b) - tu > nie trzeba dodawania wielokrotnej precyzji Jak rozumiem powyższe kroki trzeba wykonać wielokrotnie w pętli? Tyle razy ile mamy znaków? Ostatniego znaku nie mnożymy, a tylko go dodajemy do wyniku? > 2. Zamieniać na hex w pamięci już nie musisz. Nie muszę ponieważ mnożenie przez 10 jest właśnie konwersją dec na hex. > 3. Mając tak przygotowane dane wejściowe, wykonujesz odpowiednie > działanie (dodawanie, odejmowanie itp.). > 4. Zamieniać na postać dziesiętną w pamięci nie musisz. A to niżej to co to jest jak nie właśnie konwersja hex na dec? :) > 5. Konwersja na ASCII: najlepiej też metoda po jednym znaku na raz: > a) wyczyść bufor podręczny i wyjściowy > b) jeśli liczba jest zerem, to przejdź do g) > c) dzielimy liczbę przez 10 (dzielenie wielokrotnej precyzji) > d) do RESZTY z dzielenia dodajemy '0' (lub 30h) > e) zmienioną resztę z dzielenia zapisujemy w buforze podręcznym > f) wracamy do punktu a) > g) w buforze wyjściowym zapisz reszty z dzielenia znajdujące się w > buforze podręcznym, ale WSPAK (pierwszy bajt ma być ostatnim) > h) wyświetl bufor wyjściowy Dzięki za teorię. Zobaczymy jak zdołam to zaimplementować. Pozdrawiam
Re: Konwersja dużych liczb
Author: Kamil
Date: Mon, 09 Sep 2013 05:45
Date: Mon, 09 Sep 2013 05:45
126 lines
2890 bytes
2890 bytes
To moja procedura konwersji. Wydawało by się, że działa dobrze. Niestety dla niektórych danych wejściowych wystepują błędy, których nie umiem znaleźć. Przykład: 633825300114114700748351602688 : 1 = 554597137599850363154807652352 [code] stringdec2hex PROC push edi push esi push ebx push ebp lea esi, bcEdit mov mnoznik, 0Ah xor eax, eax xor ebx, ebx pobieraj: mov bl, [esi] cmp bl, 0 jz konczymy sub bl, 30h mov [argd2], bl call czysc_wynik call mnozenie push esi push edi push ecx lea esi, wynik lea edi, arg1 ; przeładowujemy dane z wynik do arg1 mov ecx, 128 rep movsd pop ecx pop edi pop esi call dodawanie inc esi jmp pobieraj konczymy: push esi push edi push ecx lea esi, arg1 mov edi, bwynik ; przeładowujemy dane z arg1 do bwynik mov ecx, 128 rep movsd pop ecx pop edi pop esi pop ebp pop ebx pop esi pop edi ret stringdec2hex endp mnozenie PROC push esi push edi lea esi, arg1 lea edi, wynik mov ecx, 18 mnozymy: mov eax, dword ptr [esi] mul mnoznik add dword ptr [edi], eax adc dword ptr [edi+4], edx adc dword ptr [edi+8], 0 adc dword ptr [edi+12], 0 adc dword ptr [edi+16], 0 jc messag1 pushf add esi, 4 add edi, 4 popf loop mnozymy jmp _do_retm messag1: mov eax, 'CF' _do_retm: pop edi pop esi ret mnozenie endp dodawanie PROC push esi lea esi, arg1 add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 pop esi ret dodawanie endp [/code] Pozdrawiam
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Mon, 09 Sep 2013 16:48
Date: Mon, 09 Sep 2013 16:48
80 lines
4751 bytes
4751 bytes
W dniu 08.09.2013 13:38, Kamil pisze: > Użytkownik "Bogdan (bogdro)" napisał: > >>> GetDlgItemText wczytuje liczby dec z kontrolki zamieniając je na >>> ASCII. > >> Tak właściwie, to już są w ASCII. Funkcja po prostu umieszcza tekst w >> buforze, nie konwertuje sama sobie np. cyfry "1" na wartość 31h, bo >> to, co robi za cyfrę "1", już ma wartość 31h. > > W kontrolce jest 1, a funkcja pobierając znak "w locie" go konwertuje > i do > bufora wpisuje już 31. Widziałem to w debuggerze. Nie do końca. W kontrolce NA EKRANIE wyświetla się "1". Ale w buforze kontrolki jest kod ASCII tego znaku, czyli 31h. Pewnie gdybyś podejrzał pamięć kontrolki, to znalazłbyś tam 31h, aby moim zdaniem trzymanie wartości w wewnętrznym buforze i konwersja "w locie" na ekran nie ma wielkiego sensu, bo co np. zrobić z innymi znakami. Tak samo, jakbyś sobie na konsoli wyświetlił znak 31h. Nie wyświetli się "49", tylko "1". >> Dobrze, to kroki powinny być takie: > >> 1. Oczyszczanie z ASCII: iterujemy po jednym znaku na raz: >> a) wczytaj kolejny znak z bufora (od przodu) >> b) odejmij 30h (kod zera w ASCII) lub po prostu '0' czy "0" >> c) bieżącą liczbę pomnóż przez 10 (mnożenie wielokrotnej precyzji z >> mojej strony) >> d) do bieżącej liczby dodaj znak pomniejszony o 30h w punkcie b) - tu >> nie trzeba dodawania wielokrotnej precyzji > > Jak rozumiem powyższe kroki trzeba wykonać wielokrotnie w pętli? Tyle > razy > ile mamy znaków? Ostatniego znaku nie mnożymy, a tylko go dodajemy do > wyniku? Wszystko się zgadza. Przed ostatnim znakiem mnożysz ostatni raz liczbę przez 10, po czym dodajesz ten ostatni znak. >> 2. Zamieniać na hex w pamięci już nie musisz. > > Nie muszę ponieważ mnożenie przez 10 jest właśnie konwersją dec na hex. Tak. Jest konwersją na postać w pamięci. >> 3. Mając tak przygotowane dane wejściowe, wykonujesz odpowiednie >> działanie (dodawanie, odejmowanie itp.). >> 4. Zamieniać na postać dziesiętną w pamięci nie musisz. > > A to niżej to co to jest jak nie właśnie konwersja hex na dec? :) Niezupełnie. To konwersja z hex/dec/oct/bin/cokolwiek na "zrozumiałą dla człowieka" formę zapisu dziesiętnego :), czyli na napis składający się ze znaków ASCII. Po tej operacji liczba nie jest w postaci dziesiętnej, ani żadnej innej logicznej. Jest konwertowana na postać gotową do wyświetlenia. Konwertować na dziesiętny można też w innym sensie, niż to, co tutaj jest. >> 5. Konwersja na ASCII: najlepiej też metoda po jednym znaku na raz: >> a) wyczyść bufor podręczny i wyjściowy >> b) jeśli liczba jest zerem, to przejdź do g) >> c) dzielimy liczbę przez 10 (dzielenie wielokrotnej precyzji) >> d) do RESZTY z dzielenia dodajemy '0' (lub 30h) >> e) zmienioną resztę z dzielenia zapisujemy w buforze podręcznym >> f) wracamy do punktu a) >> g) w buforze wyjściowym zapisz reszty z dzielenia znajdujące się w >> buforze podręcznym, ale WSPAK (pierwszy bajt ma być ostatnim) >> h) wyświetl bufor wyjściowy -- 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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Tue, 10 Sep 2013 10:22
Date: Tue, 10 Sep 2013 10:22
54 lines
2768 bytes
2768 bytes
Użytkownik "Bogdan (bogdro)" napisał: > Wszystko się zgadza. Przed ostatnim znakiem mnożysz ostatni raz > liczbę przez 10, po czym dodajesz ten ostatni znak. Dzięki Tobie przeanalizowałem jeszcze raz procedurę. Przyjrzałem się dokładnie poniższej procedurce: [code] pobieraj: mov bl, [esi] cmp bl, 0 jz _do_ret cmp bl, 20h jz pomin cmp bl, 40h ja _blad1 cmp bl, 30h jb _blad1 sub bl, 30h mul ecx ; wynik jest w eax jc _blad2 add eax, ebx [/code] Bardzo zręczne rozwiązanie. Pierwsze mnożenie jest "puste". Dzięki temu ostatni znak nie jest mnożony. Z tego wzorca korzystłem tworząć iterację wielokrotnej precyzji. Wszystko było dobrze z małymi wyjątkami: pushf add esi, 4 add edi, 4 popf O czym juz chyba wspomniałem. Brakowało odtworzenia flag w iteracji. Jednak w dalszym ciągu były błędy dla niektórych danych wejściowych. Sprawa okazała sie banalna. Było: add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 zmieniłem na: add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 adc dword ptr [esi+12], 0 Można się załamać szukając tak prostej przyczyny. Czy teraz jest już wystarczająca ilość adc? Ile ich powinno być, aby być całkowicie pewnym? Pozdrawiam i serdecznie dziękuję za pomoc.
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Tue, 10 Sep 2013 17:50
Date: Tue, 10 Sep 2013 17:50
98 lines
4758 bytes
4758 bytes
W dniu 10.09.2013 12:22, Kamil pisze:
> Użytkownik "Bogdan (bogdro)" napisał:
>
>> Wszystko się zgadza. Przed ostatnim znakiem mnożysz ostatni raz
>> liczbę przez 10, po czym dodajesz ten ostatni znak.
>
> Dzięki Tobie przeanalizowałem jeszcze raz procedurę. Przyjrzałem się
> dokładnie poniższej procedurce:
>
> [code]
>
> pobieraj:
> mov bl, [esi]
> cmp bl, 0
> jz _do_ret
> cmp bl, 20h
> jz pomin
> cmp bl, 40h
> ja _blad1
Jeśli chciałeś tym odfiltrować tylko cyfry, to jest w tym drobny
błędzik. Jeśli dobrze pamiętam, znak dwukropka przejdzie ten test, bo
dwukropek to 3A. '9' < 3a < 40h. Tak więc powinno być pewnie
cmp bl, '9'
ja _blad1
Ale może tak to było zaprojektowane (może inny mechanizm w kontrolce
nie pozwoli na wpisanie innego znaku).
Jeśli faktycznie miały być brane tylko cyfry, to czytelniej, moim
zdaniem, będzie tak:
cmp bl, ' '
jz pomin
cmp bl, '0'
jb _blad1
cmp bl, '9'
ja _blad1
Kompilator sam wstawi odpowiednie wartości bajtów w miejsce spacji ('
'), znaku '0' i '9'.
> cmp bl, 30h
> jb _blad1
> sub bl, 30h
> mul ecx ; wynik jest w eax
> jc _blad2
> add eax, ebx
> [/code]
>
> Bardzo zręczne rozwiązanie. Pierwsze mnożenie jest "puste". Dzięki
> temu ostatni znak nie jest mnożony. Z tego wzorca korzystłem tworząć
> iterację wielokrotnej precyzji. Wszystko było dobrze z małymi wyjątkami:
>
> pushf
> add esi, 4
> add edi, 4
> popf
>
> O czym juz chyba wspomniałem. Brakowało odtworzenia flag w iteracji.
> Jednak w dalszym ciągu były błędy dla niektórych danych wejściowych.
> Sprawa okazała sie banalna. Było:
>
> add dword ptr [esi], ebx
> adc dword ptr [esi+4], 0
> adc dword ptr [esi+8], 0
>
> zmieniłem na:
>
> add dword ptr [esi], ebx
> adc dword ptr [esi+4], 0
> adc dword ptr [esi+8], 0
> adc dword ptr [esi+12], 0
>
> Można się załamać szukając tak prostej przyczyny. Czy teraz jest już
> wystarczająca ilość adc? Ile ich powinno być, aby być całkowicie pewnym?
A tak mi się coś właśnie wydawało, że te bufory jakichś dziwnych
długości były, ale nie przyjrzałem się dość dokładnie.
Dodawanie (ADD i ADC) będzie tylko w mnożeniu i dodawaniu.
Wynik mnożenia może mieć co najwyżej tyle bitów, ile bitów miały
łącznie wszystkie czynniki. Jeśli mnożysz dwie liczby 32-bitowe, wynik
nie przekroczy 64 bitów (więc mieści się w EDX:EAX). Jeśli mnożysz
dwie liczby 128-bitowe (po 4 dwordy każda), wynik nie przekroczy 256
bitów (8 dwordów).
Innymi słowy, gdy pobierasz liczbę np. dwa razy (w dwóch częściach) -
z [ESI] i [ESI+4], instrukcje dodawania (pierwsze ADD i dalsze ADC)
musisz powtórzyć 4 razy, np. do [EDI], [EDI+4], [EDI+8] i [EDI+12].
Jeśli po ostatniej z tych instrukcji flaga CF jest ustawiona, to masz
przepełnienie.
A w dodawaniu instrukcje ADD/ADC powtarzasz tyle razy, ile ma dłuższy
ze składników sumy. Dla liczb 128-bitowych (4 dwordy) piszesz łącznie
4 instrukcje - jedną ADD i trzy ADC, jak w przykładzie powyżej.
--
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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Tue, 10 Sep 2013 20:27
Date: Tue, 10 Sep 2013 20:27
68 lines
4232 bytes
4232 bytes
Użytkownik "Bogdan (bogdro)" napisał:
>> [code]
>>
>> pobieraj:
>> mov bl, [esi]
>> cmp bl, 0
>> jz _do_ret
>> cmp bl, 20h
>> jz pomin
>> cmp bl, 40h
>> ja _blad1
>
> Jeśli chciałeś tym odfiltrować tylko cyfry, to jest w tym drobny
> błędzik. Jeśli dobrze pamiętam, znak dwukropka przejdzie ten test, bo
> dwukropek to 3A. '9' < 3a < 40h. Tak więc powinno być pewnie
> cmp bl, '9'
> ja _blad1
> Ale może tak to było zaprojektowane (może inny mechanizm w kontrolce
> nie pozwoli na wpisanie innego znaku).
> Jeśli faktycznie miały być brane tylko cyfry, to czytelniej, moim
> zdaniem, będzie tak:
>
> cmp bl, ' '
> jz pomin
> cmp bl, '0'
> jb _blad1
> cmp bl, '9'
> ja _blad1
>
> Kompilator sam wstawi odpowiednie wartości bajtów w miejsce spacji ('
> '), znaku '0' i '9'.
To akurat nie moja procedura. Ściągnąłem ją z sieci i nie ruszałem.
Faktycznie można wyrzucić te sprawdzenie bo kontrolkę mam zadeklarowaną jako
ES_NUMBER i oprócz cyfr niczego nie przyjmie.
>> Można się załamać szukając tak prostej przyczyny. Czy teraz jest już
>> wystarczająca ilość adc? Ile ich powinno być, aby być całkowicie pewnym?
> A tak mi się coś właśnie wydawało, że te bufory jakichś dziwnych
> długości były, ale nie przyjrzałem się dość dokładnie.
Jakich dziwnych d ługości? :) 512B. Na wszelki. Jak mnożę dwie liczby po
128B to już mam wynik co najmniej 256B. Od przybytku ...
> Dodawanie (ADD i ADC) będzie tylko w mnożeniu i dodawaniu.
> Wynik mnożenia może mieć co najwyżej tyle bitów, ile bitów miały
> łącznie wszystkie czynniki. Jeśli mnożysz dwie liczby 32-bitowe, wynik
> nie przekroczy 64 bitów (więc mieści się w EDX:EAX). Jeśli mnożysz
> dwie liczby 128-bitowe (po 4 dwordy każda), wynik nie przekroczy 256
> bitów (8 dwordów).
> Innymi słowy, gdy pobierasz liczbę np. dwa razy (w dwóch częściach) -
> z [ESI] i [ESI+4], instrukcje dodawania (pierwsze ADD i dalsze ADC)
> musisz powtórzyć 4 razy, np. do [EDI], [EDI+4], [EDI+8] i [EDI+12].
> Jeśli po ostatniej z tych instrukcji flaga CF jest ustawiona, to masz
> przepełnienie.
> A w dodawaniu instrukcje ADD/ADC powtarzasz tyle razy, ile ma dłuższy
> ze składników sumy. Dla liczb 128-bitowych (4 dwordy) piszesz łącznie
> 4 instrukcje - jedną ADD i trzy ADC, jak w przykładzie powyżej.
Właśnie. Jakieś zaćmienie. Swego czasu śledziłem w debuggerze jakieś duże
mnożenie i musiałem dodawać dużo ADC. Lepiej dać jedno więcej, niż o jedno
za mało. W programie, który ma kilka tysięcy linii kodu plus kilkanaście
funkcji wywoływanych z DLL-k łatwo coś przeoczyć, a asembler tego nie
wybacza.
Pozdrawiam i jeszcze raz dziękuję.
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Wed, 11 Sep 2013 15:44
Date: Wed, 11 Sep 2013 15:44
47 lines
2790 bytes
2790 bytes
W dniu 10.09.2013 22:27, Kamil pisze: > Użytkownik "Bogdan (bogdro)" napisał: [...] >> A tak mi się coś właśnie wydawało, że te bufory jakichś dziwnych >> długości były, ale nie przyjrzałem się dość dokładnie. > > Jakich dziwnych d ługości? :) 512B. Na wszelki. Jak mnożę dwie liczby > po 128B to już mam wynik co najmniej 256B. Od przybytku ... Mówię o równoległym poście, np. lea esi, wynik lea edi, arg1 ; przeładowujemy dane z wynik do arg1 mov ecx, 128 rep movsd 128 dwordów to 1kB. Raczej spodziewałbym się mniejszych liczb. mnozymy: mov eax, dword ptr [esi] mul mnoznik add dword ptr [edi], eax adc dword ptr [edi+4], edx adc dword ptr [edi+8], 0 adc dword ptr [edi+12], 0 adc dword ptr [edi+16], 0 Tu z kolei 5 dwordów (20 bajtów). Takie jakieś nietypowe :) add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 A to mnie chyba najbardziej zdziwiło w porównaniu z poprzednimi wielkościami - tylko 3 dwordy. [...] -- 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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Thu, 12 Sep 2013 05:20
Date: Thu, 12 Sep 2013 05:20
58 lines
3324 bytes
3324 bytes
Użytkownik "Bogdan (bogdro)" napisał: >>> A tak mi się coś właśnie wydawało, że te bufory jakichś dziwnych >>> długości były, ale nie przyjrzałem się dość dokładnie. >> >> Jakich dziwnych d ługości? :) 512B. Na wszelki. Jak mnożę dwie liczby >> po 128B to już mam wynik co najmniej 256B. Od przybytku ... > Mówię o równoległym poście, np. > lea esi, wynik > lea edi, arg1 ; przeładowujemy dane z wynik do arg1 > mov ecx, 128 > rep movsd > 128 dwordów to 1kB. Raczej spodziewałbym się mniejszych liczb. 128 dwordów to 512 bajtów. Przeładowuję całe bufory zadeklarowane: wynik db 512 dup(?) arg1 db 512 dup(?) > mnozymy: > mov eax, dword ptr [esi] > mul mnoznik > add dword ptr [edi], eax > adc dword ptr [edi+4], edx > adc dword ptr [edi+8], 0 > adc dword ptr [edi+12], 0 > adc dword ptr [edi+16], 0 > Tu z kolei 5 dwordów (20 bajtów). Takie jakieś nietypowe :) Do procedur zaglądałem w różnym czasie i coś mogło umknąć. Nie wiedziałem jeszcze tego co napisałeś o ilości ADC. Dałem za dużo na wszelki wypadek, ale to chyba niczego nie zmienia w działaniu? > add dword ptr [esi], ebx > adc dword ptr [esi+4], 0 > adc dword ptr [esi+8], 0 > A to mnie chyba najbardziej zdziwiło w porównaniu z poprzednimi W "dodawanie PROC". To już jest poprawione, ADC było za mało o jedną linijkę i były błędy. Teraz jest: add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 adc dword ptr [esi+8], 0 i działa już (chyba) dobrze. Zresztą już o tym wspomniałem. Podziwiam Twoją umijętność analizowania działania programu na podstawie źródła. Ja tego nie potrafię w takim stopniu jak Ty. Ewentualne błędy jeśli się ujawnią w wynikach znajduję przy pomocy debuggera. Pozdrawiam
Re: Konwersja dużych liczb
Author: Bogdan (bogdro)
Date: Thu, 12 Sep 2013 17:05
Date: Thu, 12 Sep 2013 17:05
92 lines
4433 bytes
4433 bytes
W dniu 12.09.2013 07:20, Kamil pisze: > Użytkownik "Bogdan (bogdro)" napisał: > >>>> A tak mi się coś właśnie wydawało, że te bufory jakichś dziwnych >>>> długości były, ale nie przyjrzałem się dość dokładnie. >>> >>> Jakich dziwnych d ługości? :) 512B. Na wszelki. Jak mnożę dwie liczby >>> po 128B to już mam wynik co najmniej 256B. Od przybytku ... > >> Mówię o równoległym poście, np. > >> lea esi, wynik >> lea edi, arg1 ; przeładowujemy dane z wynik do arg1 >> mov ecx, 128 >> rep movsd > >> 128 dwordów to 1kB. Raczej spodziewałbym się mniejszych liczb. > > 128 dwordów to 512 bajtów. Tak, zakumałem się po wysłaniu posta, ale już było późno i nie chciało mi się włączać kompa. > Przeładowuję całe bufory zadeklarowane: > > wynik db 512 dup(?) > arg1 db 512 dup(?) > >> mnozymy: > >> mov eax, dword ptr [esi] >> mul mnoznik >> add dword ptr [edi], eax >> adc dword ptr [edi+4], edx >> adc dword ptr [edi+8], 0 >> adc dword ptr [edi+12], 0 >> adc dword ptr [edi+16], 0 > >> Tu z kolei 5 dwordów (20 bajtów). Takie jakieś nietypowe :) > > Do procedur zaglądałem w różnym czasie i coś mogło umknąć. Nie > wiedziałem jeszcze tego co napisałeś o ilości ADC. Dałem za dużo na > wszelki wypadek, ale to chyba niczego nie zmienia w działaniu? Nie zmienia, o ile mieścisz się w buforze. Niedobrze byłoby np. wynik db 8 dup(?) arg1 db 8 dup(?) add dword ptr [wynik], ebx adc dword ptr [wynik+4], 0 adc dword ptr [wynik+8], 0 Bo to zamazałoby część "arg1". >> add dword ptr [esi], ebx >> adc dword ptr [esi+4], 0 >> adc dword ptr [esi+8], 0 > >> A to mnie chyba najbardziej zdziwiło w porównaniu z poprzednimi > > W "dodawanie PROC". To już jest poprawione, ADC było za mało o jedną > linijkę i były błędy. Teraz jest: > > add dword ptr [esi], ebx > adc dword ptr [esi+4], 0 > adc dword ptr [esi+8], 0 > adc dword ptr [esi+8], 0 > > i działa już (chyba) dobrze. Tylko jeśli ta ostatnia ósemka zmieni się w dwunastkę :) > Zresztą już o tym wspomniałem. Podziwiam > Twoją umijętność analizowania działania programu na podstawie źródła. > Ja tego nie potrafię w takim stopniu jak Ty. Dzięki :) > Ewentualne błędy jeśli > się ujawnią w wynikach znajduję przy pomocy debuggera. Czasem każdemu się przydaje. Czasem do własnych programów, czasem do cudzych, gdy np. rozszerzenie do Firefoksa zabija całą przeglądarkę, bo część binarna była źle skompilowana :) -- 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.Xiph.org www.TorProject.org Soft(EN): tinyurl.com/bogdro-soft
Re: Konwersja dużych liczb
Author: Kamil
Date: Fri, 13 Sep 2013 05:28
Date: Fri, 13 Sep 2013 05:28
15 lines
1954 bytes
1954 bytes
Użytkownik "Bogdan (bogdro)" napisał: >> add dword ptr [esi], ebx >> adc dword ptr [esi+4], 0 >> adc dword ptr [esi+8], 0 >> adc dword ptr [esi+8], 0 >> i działa już (chyba) dobrze. > Tylko jeśli ta ostatnia ósemka zmieni się w dwunastkę :) Jasne. Literówka. W oryginale jest 12. :) Póki co przećwiczyłem program na różnych danych i jest O.K. Pozdrawiam.
Re: Konwersja dużych liczb
Author: Kamil
Date: Sun, 15 Sep 2013 05:21
Date: Sun, 15 Sep 2013 05:21
46 lines
3294 bytes
3294 bytes
Użytkownik "Kamil" napisał: >>> add dword ptr [esi], ebx >>> adc dword ptr [esi+4], 0 >>> adc dword ptr [esi+8], 0 >>> adc dword ptr [esi+8], 0 >>> i działa już (chyba) dobrze. >> Tylko jeśli ta ostatnia ósemka zmieni się w dwunastkę :) > Jasne. Literówka. W oryginale jest 12. :) Póki co przećwiczyłem program na > różnych danych i niestety nie jet dobrze. Trzeba dać tyle adc, aby "przejechać" cały wynik, czyli 256 bajtów, bo przy niektórych danych flaga będzie się ustawiała aż do ostatniego dworda. add dword ptr [esi], ebx adc dword ptr [esi+4], 0 adc dword ptr [esi+8], 0 adc dword ptr [esi+12], 0 adc dword ptr [esi+16], 0 adc dword ptr [esi+20], 0 adc dword ptr [esi+24], 0 adc dword ptr [esi+28], 0 adc dword ptr [esi+32], 0 adc dword ptr [esi+36], 0 adc dword ptr [esi+40], 0 adc dword ptr [esi+44], 0 adc dword ptr [esi+48], 0 adc dword ptr [esi+52], 0 adc dword ptr [esi+56], 0 adc dword ptr [esi+60], 0 I z innej beczki. Na 14 stronie Twojego kursu stoi min.: "Jeśli wasz dzielnik może mieć więcej niż 32 bity, to trzeba użyć algorytmu podobnego do tego, którego uczyliśmy się w szkole." Mam nadzieję, że chodzi o szkołę podstawową. Co prawda chodziłem, ale nie pamiętam o co chodzi. Jeśli o dzielenie pisemne to no problem. Jednak jak to zaimplementować w asm? Jeśli miałbyś chwilę czasu to bardzo proszę rozwiń co masz na myśli. Zresztą w wielu opracowaniach czytam takie sformułowanie, ale na tym się kończy. A mój komputer nie potrafi lizyć ołówkiem na kartce. Pozdrawiam.
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