🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.asm
15 messages
15 total messages Started by Kamil Sun, 01 Sep 2013 20:00
Konwersja dużych liczb
#2550
Author: Kamil
Date: Sun, 01 Sep 2013 20:00
6 lines
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
#2551
Author: Bogdan (bogdro)
Date: Fri, 06 Sep 2013 17:24
27 lines
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
#2552
Author: Kamil
Date: Fri, 06 Sep 2013 21:33
22 lines
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
#2553
Author: Bogdan (bogdro)
Date: Sat, 07 Sep 2013 16:55
68 lines
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
#2554
Author: Kamil
Date: Sun, 08 Sep 2013 11:38
50 lines
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
#2555
Author: Kamil
Date: Mon, 09 Sep 2013 05:45
126 lines
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
#2556
Author: Bogdan (bogdro)
Date: Mon, 09 Sep 2013 16:48
80 lines
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
#2557
Author: Kamil
Date: Tue, 10 Sep 2013 10:22
54 lines
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
#2558
Author: Bogdan (bogdro)
Date: Tue, 10 Sep 2013 17:50
98 lines
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
#2559
Author: Kamil
Date: Tue, 10 Sep 2013 20:27
68 lines
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
#2560
Author: Bogdan (bogdro)
Date: Wed, 11 Sep 2013 15:44
47 lines
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
#2561
Author: Kamil
Date: Thu, 12 Sep 2013 05:20
58 lines
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
#2562
Author: Bogdan (bogdro)
Date: Thu, 12 Sep 2013 17:05
92 lines
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
#2563
Author: Kamil
Date: Fri, 13 Sep 2013 05:28
15 lines
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
#2564
Author: Kamil
Date: Sun, 15 Sep 2013 05:21
46 lines
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