Thread View: pl.comp.lang.asm
7 messages
7 total messages
Started by gupi manʼaʼgo
Wed, 23 Sep 2009 03:08
nie widzi stanu flag po “sub”?
Author: gupi manʼaʼgo
Date: Wed, 23 Sep 2009 03:08
Date: Wed, 23 Sep 2009 03:08
67 lines
2892 bytes
2892 bytes
mamy strukturę, której istotny fragment jak niżej:
❝
struct s_t
{ // …
unsigned n;
// …
};
❞
mamy dwie równoważne w efekcie procedury jak niżej:
❝
void
proc_1( struct s_t *s,
unsigned count
)
{ if( s->n >= count )
s->n -= count;
else
s->n = 0;
}
void
proc_2( struct s_t *s,
unsigned count
)
{ if(( s->n -= count ) > count )
s->n = 0;
}
❞
⁂
co zrobić, by kompilator ‟gcc 4.3.2” zauważył, że po odejmowaniu instru-
kcją “sub” ma flagi, które może wykorzystać zamiast umieszczać instruk-
cje “cmp”?
a może ja się mylę?
❝
<proc_1>:
8b 47 10 mov 0x10(%rdi),%eax
39 f0 cmp %esi,%eax
73 08 jae 0f
c7 47 10 00 00 00 00 movl $0x0,0x10(%rdi)
c3 retq
29 f0 0: sub %esi,%eax
89 47 10 mov %eax,0x10(%rdi)
c3 retq
<proc_2>:
8b 57 10 mov 0x10(%rdi),%edx
29 f2 sub %esi,%edx
39 d6 cmp %edx,%esi # nadmiarowa?
b8 00 00 00 00 mov $0x0,%eax
0f 43 c2 cmovae %edx,%eax
89 47 10 mov %eax,0x10(%rdi)
c3 retq
❞
⁂
może w takiej kolejności, jeśli można :-) :
1. czy się mylę?
2. czy kompilator robi to specjalnie ze względu na wewnętrzne działa-
nie ‘cpu’, któremu pomaga w czymś ta instrukcja “cmp”.
3. co zrobić, by zapis w ‟C” był ładny, a mimo to nie było nadmiarowej
“cmp”?
4. a jeśli nic nie da się zrobić łatwo :-) , to jak składniowo pytać
w ‟C” o odpowiednią flagę bez użycia wstawek “asm”?
⁂
PS „drogie koleżanki i koledzy”… aha, miało być na początku. ;->
--
/ qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!gN@8'Re. w8in/ad
\ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh
/ | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee
L_._o_O_*_^_"_'_`_ -> http://thereis.notlong.com <- `L"EnOF"
Re: nie widzi stanu flag po “sub”?
Author: Piotr Wyderski
Date: Wed, 23 Sep 2009 08:07
Date: Wed, 23 Sep 2009 08:07
6 lines
1127 bytes
1127 bytes
gupi manʼaʼgo wrote:
Zgłoś do bugzilli na stronie GCC.
Pozdrawiam
Piotr Wyderski
Re: nie widzi stanu flag po “sub”?
Author: Michoo
Date: Wed, 23 Sep 2009 09:37
Date: Wed, 23 Sep 2009 09:37
56 lines
2434 bytes
2434 bytes
gupi manʼaʼgo pisze:
> mamy strukturę, której istotny fragment jak niżej:
> ❝
> struct s_t
> { // …
> unsigned n;
> // …
> };
> ❞
> mamy dwie równoważne w efekcie procedury jak niżej:
Nie, nie są równoważne.
> ❝
> void
> proc_1( struct s_t *s,
> unsigned count
> )
> { if( s->n >= count )
> s->n -= count;
> else
> s->n = 0;
> }
Ta funkcja zmniejsza wartość o maksymalnie count nie przekraczając 0.
> void
> proc_2( struct s_t *s,
> unsigned count
> )
> { if(( s->n -= count ) > count )
> s->n = 0;
> }
Ta funkcja zmniejsza wartość o count (dokonując ewentualnych "zawinięć"
- typy są unsigned) a gdy wynik jest nadal większy od count to go
zeruje. - w porównaniu z proc_1 nie zawsze ustawia 0 gdy było przejście
przez 0 za to zawsze zeruje wynik gdy n>=2*count.
> co zrobić, by kompilator ‟gcc 4.3.2” zauważył, że po odejmowaniu instru-
> kcją “sub” ma flagi, które może wykorzystać zamiast umieszczać instruk-
> cje “cmp”?
Kompilator wygenerował to co napisałeś.
> 1. czy się mylę?
tak
> 3. co zrobić, by zapis w ‟C” był ładny, a mimo to nie było nadmiarowej
> “cmp”?
Ale to zapis _pierwszej_ funkcji jest 'ładny'. Spojrzenie na nią od razu
mówi jaki ma być efekt. Zapis drugiej funkcji imo jest przynajmniej
nieintuicyjny - coś jak jak pisanie if(!strcmp(a,b)) zamiast
if(strcmp(a,b)==0).
> PS „drogie koleżanki i koledzy”… aha, miało być na początku. ;->
P.S.
Skąd wziąłeś taki sposób formatowania?
--
Pozdrawiam
Michoo
Re: nie widzi stanu flag po “sub”?
Author: Bogdan (bogdro)
Date: Wed, 23 Sep 2009 15:56
Date: Wed, 23 Sep 2009 15:56
86 lines
3634 bytes
3634 bytes
gupi manʼaʼgo pisze:
> mamy strukturę, której istotny fragment jak niżej:
> ❝
> struct s_t
> { // …
> unsigned n;
> // …
> };
> ❞
> mamy dwie równoważne w efekcie procedury jak niżej:
> ❝
> void
> proc_1( struct s_t *s,
> unsigned count
> )
> { if( s->n >= count )
> s->n -= count;
> else
> s->n = 0;
> }
> void
> proc_2( struct s_t *s,
> unsigned count
> )
> { if(( s->n -= count ) > count )
> s->n = 0;
> }
> ❞
> ⁂
> co zrobić, by kompilator ‟gcc 4.3.2” zauważył, że po odejmowaniu instru-
> kcją “sub” ma flagi, które może wykorzystać zamiast umieszczać instruk-
> cje “cmp”?
> a może ja się mylę?
> ❝
> <proc_1>:
> 8b 47 10 mov 0x10(%rdi),%eax
> 39 f0 cmp %esi,%eax
> 73 08 jae 0f
> c7 47 10 00 00 00 00 movl $0x0,0x10(%rdi)
> c3 retq
> 29 f0 0: sub %esi,%eax
> 89 47 10 mov %eax,0x10(%rdi)
> c3 retq
> <proc_2>:
> 8b 57 10 mov 0x10(%rdi),%edx
> 29 f2 sub %esi,%edx
> 39 d6 cmp %edx,%esi # nadmiarowa?
> b8 00 00 00 00 mov $0x0,%eax
> 0f 43 c2 cmovae %edx,%eax
> 89 47 10 mov %eax,0x10(%rdi)
> c3 retq
> ❞
> ⁂
> może w takiej kolejności, jeśli można :-) :
> 1. czy się mylę?
Wygląda na to, że nie.
> 2. czy kompilator robi to specjalnie ze względu na wewnętrzne działa-
> nie ‘cpu’, któremu pomaga w czymś ta instrukcja “cmp”.
Raczej nie. Co prawda wtykanie instrukcji czasem może poprawić
wydajność kodu, ale w tym przypadku CMP faktycznie chyba jest
niepotrzebna.
> 3. co zrobić, by zapis w ‟C” był ładny, a mimo to nie było nadmiarowej
> “cmp”?
Po pierwsze, włącz optymalizacje, jeśli jeszcze tego nie zrobiłeś. Po
drugie, wypróbuj może wyrażenia warunkowe, np.
s->n = (s->n >= count)? s->n - count : 0;
s->n -= (s->n >= count)? count : s->n;
> 4. a jeśli nic nie da się zrobić łatwo :-) , to jak składniowo pytać
> w ‟C” o odpowiednią flagę bez użycia wstawek “asm”?
Nie jest mi znany żaden sposób na wykonanie tego. Jak kompilator
miałby przenieść taki operator czy funkcję na architekturę, która nie
ma podobnych flag co x86?
--
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: nie widzi stanu flag po “sub”?
Author: Bernard
Date: Thu, 24 Sep 2009 17:25
Date: Thu, 24 Sep 2009 17:25
39 lines
1947 bytes
1947 bytes
gupi manʼaʼgo wrote:
> mamy strukturę, której istotny fragment jak niżej:
> ❝
> struct s_t
> { // …
> unsigned n;
> // …
> };
> ❞
> mamy dwie równoważne w efekcie procedury jak niżej:
> ❝
> void
> proc_1( struct s_t *s,
> unsigned count
> )
> { if( s->n >= count )
> s->n -= count;
> else
> s->n = 0;
> }
> void
> proc_2( struct s_t *s,
> unsigned count
> )
> { if(( s->n -= count ) > count )
> s->n = 0;
> }
> ❞
> ⁂
> co zrobić, by kompilator ‟gcc 4.3.2” zauważył, że po odejmowaniu instru-
> kcją “sub” ma flagi, które może wykorzystać zamiast umieszczać instruk-
> cje “cmp”?
> a może ja się mylę?
Mylisz się. SUB ustawia znaczniki stosownie do wyniku odejmowania, a Ty
po odejmowaniu wykonujesz porównanie ze zmienną count, i korzystasz z
wyniku tego porównania.
I strasznie paskudnie formatujesz ten kod w C...
Re: nie widzi stanu flag po “sub”?
Author: gupi manʼaʼgo
Date: Fri, 25 Sep 2009 04:41
Date: Fri, 25 Sep 2009 04:41
148 lines
7834 bytes
7834 bytes
odpowiem tutaj niepojedynczo do odpisujących.
‟gupi manʼaʼgo” zaprogramował/a:
> mamy strukturę, której istotny fragment jak niżej:
> ❝
> struct s_t
> { // …
> unsigned n;
> // …
> };
> ❞
> mamy dwie równoważne w efekcie procedury jak niżej:
> ❝
> void
> proc_1( struct s_t *s,
> unsigned count
> )
> { if( s->n >= count )
> s->n -= count;
> else
> s->n = 0;
> }
> void
> proc_2( struct s_t *s,
> unsigned count
> )
> { if(( s->n -= count ) > count )
> s->n = 0;
> }
faktycznie druga procedura nie jest równoważna, czego nie zauważyłem po-
bieżnie patrząc w program z deasemblera, gdzie porównuje rejestr wyniko-
wy.
a historia powstania błędu jest bardzo prosta… :-)
oczywiście procedura druga powstała z kopii pierwszej, w której następ-
nie starałem się ·wyraziściej zapisać fakt· sprawdzania po przejściu wa-
rtości liczby przez zero i wkroczeniu od maksymalnej wartości liczby ca-
łkowitej bez znaku. niestety po zmienieniu znaku nierówności, podczas
modyfikowania wyrażenia po lewej stronie znaku nierówności wcisnąłem
przez pomyłkę klawisz “=”, który jest tuż przy klawiszu “-” na klawiatu-
rze. z tego powodu ;-) nie przeszedłem do poprawiania wyrażenia
po prawej stronie znaku nierówności ;-). widząc, że “s->n -= count”
jest właśnie wykonywane w pozytywnym bloku warunkowym, skasowałem
ten blok jako niepotrzebny, nie analizując już w tym momencie sensownoś-
ci całej instrukcji, lecz jedynie wartości wyrażeń cząstkowych. stąd
powstała procedura druga, która była częściowo prawdziwa dla mnie, po-
nieważ znałem proces jej powstawania, w którym wystarczyło usunąć znak
“=” i odtworzyć wszystkie pozostałe kroki od momentu jego pomyłkowego
wpisania.
czyli właściwie powinna ona wyglądać tak:
❝
void
proc_2( struct s_t *s,
unsigned count
)
{ if(( s->n - count ) > s->n )
s->n -= count;
else
s->n = 0;
}
❞
z takiej postaci powstaje oczekiwany przeze mnie program dla maszyny:
❝
<proc_2>:
8b 47 08 mov 0x8(%rdi),%eax
31 d2 xor %edx,%edx
29 f0 sub %esi,%eax
0f 42 d0 cmovb %eax,%edx
89 57 08 mov %edx,0x8(%rdi)
c3 retq
66 90 xchg %ax,%ax
❞
jakkolwiek —jak widać poniżej— kompilator wybrał optymalizację skoków
kończących procedurę jako lepszą niż korzystanie z instrukcji warunkowo
przenoszącej wartość do rejestru, kiedy —jak widać powyżej— wartość ode-
jmowania może być łatwo zgubiona z tego względu, że i tak wynik musi być
przeniesiony do pamięci, więc mamy z konieczności jedną wartość pośred-
nią, czyli rejestr kopiowany do pamięci.
kompilator wybrał tę optymalizację przypuszczalnie z powodu jego kroków
przetwarzania programu. innymi słowy— ‟gcc” nie mógł widzieć flag in-
strukcji “sub”, gdyż dla niego najpierw jest zamiana na wirtualny kod
maszyny, a później jest optymalizacja, stąd ‟gcc” ma takie flagi optyma-
lizacji dla wiersza poleceń jak te wyłączające podetapy przeszukiwania
wyrażeń pośrednich, a rejestr flag wydaje się być takim wyrażeniem poś-
rednim w sensie już posiadania oczekiwanego wyniku stanu flag.
> ❞
> ⁂
> co zrobić, by kompilator ‟gcc 4.3.2” zauważył, że po odejmowaniu instru-
> kcją “sub” ma flagi, które może wykorzystać zamiast umieszczać instruk-
> cje “cmp”?
> a może ja się mylę?
> ❝
> <proc_1>:
> 8b 47 10 mov 0x10(%rdi),%eax
> 39 f0 cmp %esi,%eax
> 73 08 jae 0f
> c7 47 10 00 00 00 00 movl $0x0,0x10(%rdi)
> c3 retq
> 29 f0 0: sub %esi,%eax
> 89 47 10 mov %eax,0x10(%rdi)
> c3 retq
> <proc_2>:
> 8b 57 10 mov 0x10(%rdi),%edx
> 29 f2 sub %esi,%edx
> 39 d6 cmp %edx,%esi # nadmiarowa?
> b8 00 00 00 00 mov $0x0,%eax
> 0f 43 c2 cmovae %edx,%eax
> 89 47 10 mov %eax,0x10(%rdi)
> c3 retq
> ❞
> ⁂
> może w takiej kolejności, jeśli można :-) :
> 1. czy się mylę?
> 2. czy kompilator robi to specjalnie ze względu na wewnętrzne działa-
> nie ‘cpu’, któremu pomaga w czymś ta instrukcja “cmp”.
> 3. co zrobić, by zapis w ‟C” był ładny, a mimo to nie było nadmiarowej
> “cmp”?
> 4. a jeśli nic nie da się zrobić łatwo :-) , to jak składniowo pytać
> w ‟C” o odpowiednią flagę bez użycia wstawek “asm”?
1. czyli czy się myliłem? wcisnąłem nadmiarowy klawisz podczas wpi-
sywania drugiej procedury, z której to pomyłki w kolejnych krokach pow-
stała błędna “proc_2”.
2. czy kompilator specjalnie wstawia “cmp”. jak widać po sekwencjach
instrukcji maszyny z deasemblera, na ujętych przypadkach— nie wygląda
na to. ale nie radzi sobie dobrze z zamianą kolejności “cmp” i “sub”
w przypadku ogólnym (“proc_1”). i nie można w zgodzie z prawdą w takim
wypadku powiedzieć, że „kompilator robi to co jest napisane”. ‟gcc”
nie ma możliwości wyłączenia optymalizacji nie naruszających granic in-
strukcji określonych w standardzie ‟C” bez wyłączenia optymalizacji in-
strukcji maszynowych. zresztą komu by to było potrzebne oprócz chcą-
cych mieć postać programu zgodną ze standardem ‟C” zamiast oczekiwaną
wykonawczo i efektywną. jednak w takim stanie rzeczy optymalizacja mó-
wi tylko o programie jako takim, a nie programie zgodnym ze standardem
‟C”.
3. ‚ładny’ zapis? nowa postać “proc_2”.
4. o flagę przepełnienia dla całkowitych bez znaku oczywiście można
pytać przy pomocy odejmowania nie zachowującego wartości
“a - b > a”, z czego można by zrobić nawet gotowe makropolecenia umożli-
wiające wykorzystanie cechy dopełniania do 2 na różnych typach liczb ca-
łkowitych i odejście od —wg mnie bezzasadnego— funkcyjnego (od języków
funkcyjnych) podejścia do programowania w ‟C”. :-)
⁂
mimo gburowatości niektórych odpowiedzi, udało się wykorzystać grupy dy-
skusyjne do rozmowy…? ;-] i to jeszcze na dwóch grupach. temat chyba
dobrze pasuje do obu? :-)
--
qo |) CPL<=dataDPL CPL==/>=codeDPL:conform'/nc';max=CPL! AV0ID bHp
_x/ , CPL<=TSS,gateDPL CPL>=/==dest_DPL:/(jmp&nc') ,RPL!- #GP -o0o
| ng __ -- __ -- __ -- __ -- __ -- __ -- __ -- __ -x86-, EV3RY o0o
,__ -- __ -- Current/Requested/DescriptorPrivilegeLevel C/R/DPL , d4y m:#=
Re: nie widzi stanu flag po “sub”?
Author: gupi manʼaʼgo
Date: Fri, 25 Sep 2009 05:38
Date: Fri, 25 Sep 2009 05:38
25 lines
2103 bytes
2103 bytes
‟Bogdan (bogdro)” zaprogramował/a: >> 3. co zrobić, by zapis w ‟C” był ładny, a mimo to nie było >> nadmiarowej “cmp”? > > Po pierwsze, włącz optymalizacje, jeśli jeszcze tego nie zrobiłeś. Po > drugie, wypróbuj może wyrażenia warunkowe, np. > > s->n = (s->n >= count)? s->n - count : 0; s->n -= (s->n >= count)? count > : s->n; w poprawionej formie —jak w mojej odpowiedzi na własny list do wszys- tkich odpowiadających— dają ten sam wynik— oczekiwany. >> 4. a jeśli nic nie da się zrobić łatwo :-) , to jak składniowo >> pytać w ‟C” o odpowiednią flagę bez użycia wstawek “asm”? > > Nie jest mi znany żaden sposób na wykonanie tego. Jak kompilator > miałby przenieść taki operator czy funkcję na architekturę, która nie ma > podobnych flag co x86? a to pytanie chyba pozostawię otwartym, oczywiście w rozumieniu go jako: „jak pytać o znaczenie przepełnienia na maszynach, które mają je inne?”. -- / qo |) :@=N%_g=v=a=g_eD_e=c()=d=8! =%!gN@8'Re. w8in/ad \ _x/ , ;h-%-a'hA'H4,X0'Xo~xo~xO,R`-%EXp01ITed: *-7/+eh / | ng `-%__%--'__%--'__%--~__%--^%B`/$qV3r[o; &GooMee L_._o_O_*_^_"_'_`_ -> http://thereis.notlong.com <- `L"EnOF"
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