Thread View: pl.comp.lang.asm
5 messages
5 total messages
Started by Kamil
Fri, 06 Sep 2013 01:57
Odejmowanie dużych liczb
Author: Kamil
Date: Fri, 06 Sep 2013 01:57
Date: Fri, 06 Sep 2013 01:57
85 lines
3278 bytes
3278 bytes
Witam
Na stronie Bogdana jest min. procedura odejmowania:
mov eax, [arg1]
sub eax, [arg2] ; odejmujemy 2 pierwsze części
mov [wynik], eax ; i zapisujemy wynik
; flaga CF mówi, czy była pożyczka
mov eax, [arg1+4]
sbb eax, [arg2+4] ; odejmujemy razem z pożyczk? (CF),
; jeśli w poprzednim odejmowaniu
; musieli?my co? pożyczać
mov [wynik+4], eax ; wynik: [arg1+4]-[arg2+4]-pożyczka
; z pierwszego odejmowania
; CF teraz zawiera pożyczkę z SBB
; podobnie reszta działania:
mov eax, [arg1+8]
sbb eax, [arg2+8]
mov [wynik+8], eax
mov eax, [arg1+12]
sbb eax, [arg2+12]
mov [wynik+12], eax
jc arg1_mniejszy_od_arg2
Moja implementacja wygląda tak:
odejmij PROC
push esi
push edi
push ebx
push ebp
mov eax, [arg1]
sub eax, [arg2] ; odejmujemy 2 pierwsze części
mov [wynik], eax ; i zapisujemy wynik
; flaga CF mówi, czy była pożyczka
mov eax, [arg1+4]
sbb eax, [arg2+4] ; odejmujemy razem z pożyczk? (CF),
; jeśli w poprzednim odejmowaniu
; musieli?my co? pożyczać
mov [wynik+4], eax ; wynik: [arg1+4]-[arg2+4]-pożyczka
; z pierwszego odejmowania
; CF teraz zawiera pożyczkę z SBB
; podobnie reszta działania:
mov eax, [arg1+8]
sbb eax, [arg2+8]
mov [wynik+8], eax
mov eax, [arg1+12]
sbb eax, [arg2+12]
mov [wynik+12], eax
jc arg1_mniejszy_od_arg2
arg1_mniejszy_od_arg2:
pop ebp
pop ebx
pop edi
pop esi
ret
odejmij endp
mam następujące pytania:
- Co sie stanie w razie wystąpienia sytuacji spełniącej warunek skoku jc?
Czy linia mov [wynik+12], eax się wykona? Jaki będzie wynik?
- co się stanie kiedy już w peerwszych argumentach będzie arg1 < arg2
- cfzy jc nie powinno być po każdym odejmowaniu?
Pozdrawiam
Re: Odejmowanie dużych liczb
Author: Kamil
Date: Fri, 06 Sep 2013 06:04
Date: Fri, 06 Sep 2013 06:04
53 lines
1862 bytes
1862 bytes
Użytkownik "Kamil" napisał: Ta procedura działa błędnie dla niektórych danych wejściowych. Pryczyny nie znalazłem. Może komuś uda się znaleźć błąd? [code] push edi push esi push ebx push ebp mov esi, odarg1 mov edi, odkarg2 mov ebx, odwynik mov ecx, 20 mov eax, pam [esi] sub eax, pam [edi] mov pam [ebx], eax odejmujemy: mov eax, pam [esi+4] sbb eax, pam [edi+4] mov pam [ebx+4], eax jc arg1_mniejszy_od_arg2 add esi, 4 add edi, 4 add ebx, 4 loop odejmujemy arg1_mniejszy_od_arg2: pop ebp pop ebx pop esi pop edi mov eax, 'aw' jmp _do_ret_od2 _do_ret_od2: ret [/code] Pozdrawiam
Re: Odejmowanie dużych liczb
Author: Bogdan (bogdro)
Date: Fri, 06 Sep 2013 17:29
Date: Fri, 06 Sep 2013 17:29
109 lines
4058 bytes
4058 bytes
W dniu 06.09.2013 03:57, Kamil pisze: > Witam > > Na stronie Bogdana jest min. procedura odejmowania: > > > mov eax, [arg1] > sub eax, [arg2] ; odejmujemy 2 pierwsze części > mov [wynik], eax ; i zapisujemy wynik > ; flaga CF mówi, czy była pożyczka > > mov eax, [arg1+4] > sbb eax, [arg2+4] ; odejmujemy razem z pożyczk? (CF), > ; jeśli w poprzednim odejmowaniu > ; musieli?my co? pożyczać > > mov [wynik+4], eax ; wynik: [arg1+4]-[arg2+4]-pożyczka > ; z pierwszego odejmowania > ; CF teraz zawiera pożyczkę z SBB > ; podobnie reszta działania: > > mov eax, [arg1+8] > sbb eax, [arg2+8] > mov [wynik+8], eax > > mov eax, [arg1+12] > sbb eax, [arg2+12] > mov [wynik+12], eax > > jc arg1_mniejszy_od_arg2 > > Moja implementacja wygląda tak: > > odejmij PROC > > push esi > push edi > push ebx > push ebp > > > mov eax, [arg1] > sub eax, [arg2] ; odejmujemy 2 pierwsze części > mov [wynik], eax ; i zapisujemy wynik > ; flaga CF mówi, czy była pożyczka > > mov eax, [arg1+4] > sbb eax, [arg2+4] ; odejmujemy razem z pożyczk? (CF), > ; jeśli w poprzednim odejmowaniu > ; musieli?my co? pożyczać > > mov [wynik+4], eax ; wynik: [arg1+4]-[arg2+4]-pożyczka > ; z pierwszego odejmowania > ; CF teraz zawiera pożyczkę z SBB > ; podobnie reszta działania: > > mov eax, [arg1+8] > sbb eax, [arg2+8] > mov [wynik+8], eax > > mov eax, [arg1+12] > sbb eax, [arg2+12] > mov [wynik+12], eax > > jc arg1_mniejszy_od_arg2 > > arg1_mniejszy_od_arg2: > > pop ebp > pop ebx > pop edi > pop esi > > ret > > odejmij endp > > mam następujące pytania: > > - Co sie stanie w razie wystąpienia sytuacji spełniącej warunek skoku jc? Nic. To jest "informacja dla autora", że gdyby chciał tę sytuację obsłużyć, to może zrobić to w ten sposób. > Czy linia mov [wynik+12], eax się wykona? Tak, bo jest przed skokiem. > Jaki będzie wynik? Ten sam. Konkretnie - ujemny. > - co się stanie kiedy już w peerwszych argumentach będzie arg1 < arg2 Nic. Liczby będą się dalej odejmować, tylko flaga CF będzie gdzieniegdzie ustawiona. > - cfzy jc nie powinno być po każdym odejmowaniu? Nie. Sytuacja ustawienia flagi CF jest obsługiwana przez zastosowanie instrukcji SBB (odejmowanie "z pożyczką") zamiast SUB, czyli zwykłego odejmowania. -- 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: Odejmowanie dużych liczb
Author: Bogdan (bogdro)
Date: Fri, 06 Sep 2013 17:36
Date: Fri, 06 Sep 2013 17:36
71 lines
2673 bytes
2673 bytes
W dniu 06.09.2013 08:04, Kamil pisze: > Użytkownik "Kamil" napisał: > > Ta procedura działa błędnie dla niektórych danych wejściowych. Czym otrzymany wynik różni się od oczekiwanego? > Pryczyny nie znalazłem. Może komuś uda się znaleźć błąd? > > [code] > > push edi > push esi > push ebx > push ebp > > mov esi, odarg1 > mov edi, odkarg2 > mov ebx, odwynik > mov ecx, 20 > > mov eax, pam [esi] > sub eax, pam [edi] > mov pam [ebx], eax Bez definicji "pam" może być trudno to zinterpretować. > odejmujemy: > > mov eax, pam [esi+4] > sbb eax, pam [edi+4] > mov pam [ebx+4], eax > > jc arg1_mniejszy_od_arg2 > > add esi, 4 > add edi, 4 > add ebx, 4 > > loop odejmujemy Wiesz, że odejmujesz 21 "czwórek", prawda? ECX = 20, ale pozycję [0] obsługujesz przed pętlą, a w pętli obsługujesz pozycje [4], [8], [12], ..., [80], czyli łącznie bajty na offsetach od 0 do 83 włącznie. > arg1_mniejszy_od_arg2: > > pop ebp > pop ebx > pop esi > pop edi > > mov eax, 'aw' > jmp _do_ret_od2 > > _do_ret_od2: > > ret > > [/code] > > Pozdrawiam > -- 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: Odejmowanie dużych liczb
Author: Kamil
Date: Fri, 06 Sep 2013 21:54
Date: Fri, 06 Sep 2013 21:54
54 lines
2509 bytes
2509 bytes
Użytkownik "Bogdan (bogdro)" napisał:
>> Ta procedura działa błędnie dla niektórych danych wejściowych.
> Czym otrzymany wynik różni się od oczekiwanego?
Dla np. 633825300114114700748351602688 wynik dzielenia wynosi
554597137599850363154807652352
>> Pryczyny nie znalazłem. Może komuś uda się znaleźć błąd?
> Bez definicji "pam" może być trudno to zinterpretować.
Przepraszam za przeoczenie. "pam" equ dword ptr
>> mov eax, pam [esi+4]
>> sbb eax, pam [edi+4]
>> mov pam [ebx+4], eax
>>
>> jc arg1_mniejszy_od_arg2
>>
>> add esi, 4
>> add edi, 4
>> add ebx, 4
>> loop odejmujemy
> Wiesz, że odejmujesz 21 "czwórek", prawda? ECX = 20, ale pozycję [0]
> obsługujesz przed pętlą, a w pętli obsługujesz pozycje [4], [8], [12],
> ..., [80], czyli łącznie bajty na offsetach od 0 do 83 włącznie.
To akurat jest jasne. Wydaje się, że jeden błąd znalazłem. Otóż jeśli po sbb
zostanie ustawiona flaga to linijki
add esi, 4
add edi, 4
add ebx, 4
ją skasują. Ma być tak:
pushf
add esi, 4
add edi, 4
add ebx, 4
popf
Okazuje się, że "skaracanie" tekstu źródłowego procedur jest ryzykowne.
Lepiej stosować je w pełnym rozwinięciu wg. Twoich tutoriali. Wtedy nie ma
problemów.
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