RTV forum PL | NewsGroups PL

Możliwość wywołania funkcji Rysuj z parametrami bezpośrednio w WinAVR jak to zrobić?

Problem lekko OT, ale w WinAVR ;-)

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Możliwość wywołania funkcji Rysuj z parametrami bezpośrednio w WinAVR jak to zrobić?

Goto page 1, 2, 3, 4, 5  Next

Grzegorz Kurczyk
Guest

Thu Jun 11, 2009 11:03 am   



Witam Kolegów.

Tak sobie kombinuję. Jest struktura:

typedef struct {
uchar x;
uchar y;
uchar w;
uchar h;
} tRect;


i przykładowa funkcja:
void Rysuj(tRect r) {
Prostokat(r.x, r.y, r.x+r.w, r.y+r.h);
}

Pojawił mi się problem składni języka C i nie mogę się doszukać jak to
obejść. Funkcję z poziomu programu głównego możemy wywołać:

int main (void) {
tRect r;
r.x = 10;
r.y = 20;
r.w = 100;
r.h = 10;
Rysuj(r);
}

Czy jakoś można wywołać funkcję rysuj podając jej parametry bezpośrednio
bez uprzedniego definiowania zmiennej r ?
Coś w stylu:
Rysuj({10,20,100,10});
co oczywiście nie działa :-)

Pewnie, że można zrobić funkcję:
void Rysuj(char x, char y, char w, char h) {
Prostokat(x, y, x+w, y+h);
}
i po kłopocie, ale chodzi mi o pewną "sztuczkę" związaną z optymalizacją
WinAVR w zakresie przekazywania parametrów do funkcji za pośrednictwem
rejestrów.

Pozdrawiam
Grzegorz

Zbych
Guest

Thu Jun 11, 2009 11:27 am   



Grzegorz Kurczyk pisze:

Quote:
Pojawił mi się problem składni języka C i nie mogę się doszukać jak to
obejść. Funkcję z poziomu programu głównego możemy wywołać:

int main (void) {
tRect r;
r.x = 10;
r.y = 20;
r.w = 100;
r.h = 10;
Rysuj(r);
}

można krócej:

tRect r = {1,2,3,4};
Rysuj(r);

Quote:
Czy jakoś można wywołać funkcję rysuj podając jej parametry bezpośrednio
bez uprzedniego definiowania zmiennej r ?

Na c++ trzeba się przesiąść.

--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
ale kto by tak pieknie gwizdal...

Zbych
Guest

Thu Jun 11, 2009 11:46 am   



Quote:
Grzegorz Kurczyk pisze:
Czy jakoś można wywołać funkcję rysuj podając jej parametry
bezpośrednio bez uprzedniego definiowania zmiennej r ?

Przyszło mi jeszcze do głowy makro:

#define RECT(__a,__b,__c,__d) ({static const tRect __r =
{(__a),(__b),(__c),(__d)}; __r;})

Wtedy można napisać tak:

Rysuj(RECT(1,2,3,4));

Powinieneś tylko mieć włączone rozszerzenie standardu do gnu99.


--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
ale kto by tak pieknie gwizdal...

J.F.
Guest

Thu Jun 11, 2009 12:59 pm   



On Thu, 11 Jun 2009 13:55:13 -0400, T.M.F. wrote:
Quote:
Poza tym co radzi ci Zbych jesli zalezy ci na efektywnosci to przekazuj
strukture tRect przez wskazanie:
void Rysuj(tRect &t);
Inaczej kompilator musi utworzyc kopie obiektu tRect i ta kopie dopiero
przekazac do funkcji.

W C++ moze to byc faktycznie kosztowne.

W pozostalych sytuacjach trzeba by spojrzec w kod wynikowy co lepiej
kompilatorowi wyszlo.

A wracajac do meritum .. wychodzi na to ze najlepiej byloby odwrocic
sprawe - zrobic funcje z 4 parametrami, a nad nia ewentualnie
nadbudowac wersje ze struktura.
I nie korzystac z niej bez potrzeby :-)

J.

T.M.F.
Guest

Thu Jun 11, 2009 1:40 pm   



W dniu 11.06.2009 06:03, Grzegorz Kurczyk pisze:
Quote:
Witam Kolegów.

Tak sobie kombinuję. Jest struktura:

typedef struct {
uchar x;
uchar y;
uchar w;
uchar h;
} tRect;


i przykładowa funkcja:
void Rysuj(tRect r) {
Prostokat(r.x, r.y, r.x+r.w, r.y+r.h);
}

Pojawił mi się problem składni języka C i nie mogę się doszukać jak to
obejść. Funkcję z poziomu programu głównego możemy wywołać:

int main (void) {
tRect r;
r.x = 10;
r.y = 20;
r.w = 100;
r.h = 10;
Rysuj(r);
}

Czy jakoś można wywołać funkcję rysuj podając jej parametry bezpośrednio
bez uprzedniego definiowania zmiennej r ?
Coś w stylu:
Rysuj({10,20,100,10});
co oczywiście nie działa :-)

Pewnie, że można zrobić funkcję:
void Rysuj(char x, char y, char w, char h) {
Prostokat(x, y, x+w, y+h);
}
i po kłopocie, ale chodzi mi o pewną "sztuczkę" związaną z optymalizacją
WinAVR w zakresie przekazywania parametrów do funkcji za pośrednictwem
rejestrów.

Pozdrawiam
Grzegorz


T.M.F.
Guest

Thu Jun 11, 2009 1:40 pm   



Quote:
Poza tym co radzi ci Zbych jesli zalezy ci na efektywnosci to przekazuj
strukture tRect przez wskazanie:
void Rysuj(tRect&t);
Inaczej kompilator musi utworzyc kopie obiektu tRect i ta kopie dopiero
przekazac do funkcji.

W C++ moze to byc faktycznie kosztowne.

W C tez powinno byc kosztowne. Bo skad kompilator ma wiedziec, ze Rysuj
nie modyfikuje struktury tRect? Mozna go wspomoc poprzez const, ale IMHO
wskazanie ma pare zalet o ktorych za chwile.

Quote:
W pozostalych sytuacjach trzeba by spojrzec w kod wynikowy co lepiej
kompilatorowi wyszlo.

A wracajac do meritum .. wychodzi na to ze najlepiej byloby odwrocic
sprawe - zrobic funcje z 4 parametrami, a nad nia ewentualnie
nadbudowac wersje ze struktura.
I nie korzystac z niej bez potrzeby Smile

Niekoniecznie. 4 parametry to w idealnym przypadku 4 8-bitowe rejestry.
Zazwyczaj wiaze sie to z ich wczesniejszym odlozeniem na stosie i potem
ponownym pobraniem. Przy przekazaniu przez wskazanie mamy tylko dwa
8-bitowe rejestry wskazujace na strukture, co wiaze sie zmniejszym
nakladem na przekazanie parametrow. W procedurze czesto jest to
optymalizowane jako LD Rx,Z+y, lub podobne.
OT: to co chce zrobic autor wydaje sie lepiej zrealizowac w C++. BTW, w
moim repozytorium SVN jest przyklad sterownika do S65 z cala biblioteka
prymitywow w C++.

T.M.F.
Guest

Thu Jun 11, 2009 1:40 pm   



W dniu 11.06.2009 06:03, Grzegorz Kurczyk pisze:
Quote:
Witam Kolegów.

Tak sobie kombinuję. Jest struktura:

typedef struct {
uchar x;
uchar y;
uchar w;
uchar h;
} tRect;


i przykładowa funkcja:
void Rysuj(tRect r) {
Prostokat(r.x, r.y, r.x+r.w, r.y+r.h);
}

Poza tym co radzi ci Zbych jesli zalezy ci na efektywnosci to przekazuj
strukture tRect przez wskazanie:
void Rysuj(tRect &t);
Inaczej kompilator musi utworzyc kopie obiektu tRect i ta kopie dopiero
przekazac do funkcji.

J.F.
Guest

Thu Jun 11, 2009 2:52 pm   



On Thu, 11 Jun 2009 14:28:34 -0400, T.M.F. wrote:
Quote:
void Rysuj(tRect&t);
Inaczej kompilator musi utworzyc kopie obiektu tRect i ta kopie dopiero
przekazac do funkcji.

W C++ moze to byc faktycznie kosztowne.

W C tez powinno byc kosztowne. Bo skad kompilator ma wiedziec, ze Rysuj
nie modyfikuje struktury tRect?

Nie musi wiedziec. Ma wrzucic cala na stos, co powinno pojsc dosc
szybko.

Quote:
W pozostalych sytuacjach trzeba by spojrzec w kod wynikowy co lepiej
kompilatorowi wyszlo.
A wracajac do meritum .. wychodzi na to ze najlepiej byloby odwrocic
sprawe - zrobic funcje z 4 parametrami, a nad nia ewentualnie
nadbudowac wersje ze struktura.
I nie korzystac z niej bez potrzeby :-)

Niekoniecznie. 4 parametry to w idealnym przypadku 4 8-bitowe rejestry.
Zazwyczaj wiaze sie to z ich wczesniejszym odlozeniem na stosie i potem
ponownym pobraniem. Przy przekazaniu przez wskazanie mamy tylko dwa
8-bitowe rejestry wskazujace na strukture, co wiaze sie zmniejszym
nakladem na przekazanie parametrow. W procedurze czesto jest to
optymalizowane jako LD Rx,Z+y, lub podobne.

Sa to pewne zalozenia i wymagaja odpowiedniego procka.
W wielu moze wyjsc odwrotnie.

Quote:
OT: to co chce zrobic autor wydaje sie lepiej zrealizowac w C++.

No, Jesli pamietacie Piotra Wyderskiego to on to polecal od dawna,
i chyba mamy przyklad ze by sie przydalo.

Choc w sumie .. jedno makro, troche dyscypliny [potrzebnej tez w ++] i
mozna w zwyklym C miec trzy wersje do wyboru, dopasowujac sie do
procka.

J.

Grzegorz Kurczyk
Guest

Thu Jun 11, 2009 3:16 pm   



Dziękuję wszystkim za odzew :-)

Metody opisywane przez Kolegów męczyłem już wcześniej (poza przesiadką
na C++), ale nie przynoszą one spodziewanego rezultatu. Może sprecyzuję
o co mi chodzi. Sprawa jest czysto "akademicka" i wynika z mojego
pewnego rodzaju "zboczenia" w dążeniu do absurdalnej optymalizacji kodu
wynikowego Wink
Jest tak. Funkcja zdefiniowana tradycyjnie:

void ProgressBar(char x, char y, char w, char h, char value) {
....
}

przy wywołaniu:
ProgressBar(0, 90, 128, 5, y);

otrzymujemy w kodzie wynikowym:
37e2: 0b 2d mov r16, r11
37e4: 25 e0 ldi r18, 0x05 ; 5
37e6: 40 e8 ldi r20, 0x80 ; 128
37e8: 6a e5 ldi r22, 0x5A ; 90
37ea: 80 e0 ldi r24, 0x00 ; 0
37ec: 0e 94 b4 17 call 0x2f68 ; 0x2f68 <ProgressBar>


I to co mnie "wkurza", to czemu łachudra przekazuje parametry w
rejestrach r16, r18, r20, r22, r24 niejako promując typ char do int ?
Jakby nie mógł po kolei r16..r20.
Oczywiście w tym przypadku nie ma to większego znaczenia, ale przy
większej ilości parametrów przekazywanych do funkcji i/lub większej
ilości zmiennych lokalnych funkcji, zaczyna się kombinacja ze stosem lub
z dolnymi rejestrami. Kompilator w pewnym sensie "szatkuje" sobie obszar
rejestrów doprowadzając do sytuacji, że w pewnym momencie brakuje np
czterech kolejnych rejestrów do zapamiętania lokalnej zmiennej typu long
choć pojedynczych wolnych rejestrów jest wystarczająca ilość.

Przekazując do funkcji zmienną typu long lub wspomniany wcześniej typ
tRect wszystko jest cacy w kolejnych rejestrach r20..r23.

Tak jak wspomniałem dyskusja jest czysto akademicka w stylu: "czemu
kompilator robi to akurat tak, choć w assemblerze wygodniej byłoby
inaczej ?" ;-)

Chyba, że w kompilatorze jest jakaś przełącznik, coby przy przekazywaniu
parametrów char nie był "przekształcany" w int. Pamiętam, że starsze
wersje przy poleceniu switch(zmienna_typu_char) wykonywały niepotrzebne
dwubajtowe porównania na typie int.

Pozdrawiam
Grzegorz

J.F.
Guest

Thu Jun 11, 2009 4:02 pm   



On Thu, 11 Jun 2009 16:16:54 +0200, Grzegorz Kurczyk wrote:
Quote:
o co mi chodzi. Sprawa jest czysto "akademicka" i wynika z mojego
pewnego rodzaju "zboczenia" w dążeniu do absurdalnej optymalizacji kodu
wynikowego Wink

Nie wysilaj sie, wez lepszy procek :-)

Quote:
void ProgressBar(char x, char y, char w, char h, char value) {
przy wywołaniu:
ProgressBar(0, 90, 128, 5, y);

otrzymujemy w kodzie wynikowym:
37e2: 0b 2d mov r16, r11
37e4: 25 e0 ldi r18, 0x05 ; 5
37e6: 40 e8 ldi r20, 0x80 ; 128
37e8: 6a e5 ldi r22, 0x5A ; 90
37ea: 80 e0 ldi r24, 0x00 ; 0
37ec: 0e 94 b4 17 call 0x2f68 ; 0x2f68 <ProgressBar

I to co mnie "wkurza", to czemu łachudra przekazuje parametry w
rejestrach r16, r18, r20, r22, r24 niejako promując typ char do int ?

Ja juz nie pamietam .. ale czy to gdzies nie jest w standardzie C
zapisane ? cos podobnego bylo .. konwersja parametrow, a moze
wyrownanie [alignment] .. Moze trzeba opcje kompilatora sprawdzic ?

J.

Grzegorz Kurczyk
Guest

Thu Jun 11, 2009 4:30 pm   



Użytkownik J.F. napisał:
Quote:

Nie wysilaj sie, wez lepszy procek Smile

Wiieeeeeem Smile ale to takie zboczenie już chyba nieuleczalne Smile z
czasów 8080+2716, 8748 itp. na zasadzie czemu procedura ma zajmować 28
bajtów i 35 taktów zegara skoro może 23 bajty i tylko 31 taktów SmileSmileSmile
W sumie to procek, na którym rzeźbię w tej chwili ma zasobów aż nadto,
ale czasem tak dla sportu zaglądam do pliku .lss i patrzę co tam
kompilator wysmarował. Choć czasem to musiałem do niego zajrzeć, bo
niekiedy program zachowywał się nie do końca tak jak wynikałoby to z
kodu źródłowego.

Pozdrawiam
Grzegorz

Zbych
Guest

Thu Jun 11, 2009 6:45 pm   



Grzegorz Kurczyk pisze:

Quote:
ale czasem tak dla sportu zaglądam do pliku .lss i patrzę co tam
kompilator wysmarował.

Moja rada - nie zaglądać. Ja co zajrzę to rzucam mięsem (a bo to brak
optymalizacji przy adresowaniu tablic struktur, albo przy pobieraniu
wielu stałych z flasha, albo przy alokacji ramki na stosie przy
przekazywaniu parametrów itd.)

--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
ale kto by tak pieknie gwizdal...

Adam Dybkowski
Guest

Thu Jun 11, 2009 7:51 pm   



Zbych pisze:

Quote:
ale czasem tak dla sportu zaglądam do pliku .lss i patrzę co tam
kompilator wysmarował.

Moja rada - nie zaglądać. Ja co zajrzę to rzucam mięsem (a bo to brak
optymalizacji przy adresowaniu tablic struktur, albo przy pobieraniu
wielu stałych z flasha, albo przy alokacji ramki na stosie przy
przekazywaniu parametrów itd.)

A ja ostatnio sporo dziubię na ARMa w gcc i przeglądając listing
asemblerowy co chwila dziwię się, jak to optymalizator ładnie
wykoncypował, że sam bym lepiej w asemblerze nie napisał. Tak że jedyna
rada - zmienić platformę.

--
Adam Dybkowski
http://dybkowski.net/

Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.

Zbych
Guest

Thu Jun 11, 2009 8:01 pm   



Adam Dybkowski pisze:

Quote:
A ja ostatnio sporo dziubię na ARMa w gcc i przeglądając listing
asemblerowy co chwila dziwię się, jak to optymalizator ładnie
wykoncypował, że sam bym lepiej w asemblerze nie napisał. Tak że jedyna
rada - zmienić platformę.

To pokaż mi jeszcze ARMa, który po zatrzymaniu zegara pobiera < 1uA.


--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
ale kto by tak pieknie gwizdal...

Zbych
Guest

Thu Jun 11, 2009 8:02 pm   



T.M.F. pisze:
Quote:
ale czasem tak dla sportu zaglądam do pliku .lss i patrzę co tam
kompilator wysmarował.
Moja rada - nie zaglądać. Ja co zajrzę to rzucam mięsem (a bo to brak
optymalizacji przy adresowaniu tablic struktur, albo przy pobieraniu
wielu stałych z flasha, albo przy alokacji ramki na stosie przy
przekazywaniu parametrów itd.)

A ja ostatnio sporo dziubię na ARMa w gcc i przeglądając listing
asemblerowy co chwila dziwię się, jak to optymalizator ładnie
wykoncypował, że sam bym lepiej w asemblerze nie napisał. Tak że jedyna
rada - zmienić platformę.

Cos Zbych przesadza.

Nie przesadza, wystarczy sprawdzić.

--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
ale kto by tak pieknie gwizdal...

Goto page 1, 2, 3, 4, 5  Next

elektroda NewsGroups Forum Index - Elektronika Polska - Możliwość wywołania funkcji Rysuj z parametrami bezpośrednio w WinAVR jak to zrobić?

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map