eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaProblem lekko OT, ale w WinAVR ;-)
Ilość wypowiedzi w tym wątku: 61

  • 1. Data: 2009-06-11 10:03:52
    Temat: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    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


  • 2. Data: 2009-06-11 10:27:10
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    Grzegorz Kurczyk pisze:

    > 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);

    > 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...


  • 3. Data: 2009-06-11 10:46:43
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    > 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...


  • 4. Data: 2009-06-11 11:59:55
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: J.F. <j...@p...onet.pl>

    On Thu, 11 Jun 2009 13:55:13 -0400, T.M.F. wrote:
    >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.


  • 5. Data: 2009-06-11 13:52:51
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: J.F. <j...@p...onet.pl>

    On Thu, 11 Jun 2009 14:28:34 -0400, T.M.F. wrote:
    >>> 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.

    >> 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.

    >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.


  • 6. Data: 2009-06-11 14:16:54
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    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 ;-)
    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


  • 7. Data: 2009-06-11 15:02:43
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: J.F. <j...@p...onet.pl>

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

    Nie wysilaj sie, wez lepszy procek :-)

    >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.


  • 8. Data: 2009-06-11 15:30:40
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    Użytkownik J.F. napisał:
    >
    > Nie wysilaj sie, wez lepszy procek :-)

    Wiieeeeeem :-) ale to takie zboczenie już chyba nieuleczalne :-) 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 :-):-):-)
    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


  • 9. Data: 2009-06-11 17:45:47
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    Grzegorz Kurczyk pisze:

    > 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...


  • 10. Data: 2009-06-11 17:54:42
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    W dniu 11.06.2009 06:03, Grzegorz Kurczyk pisze:
    > 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

strony : [ 1 ] . 2 ... 7


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: