Problem lekko OT, ale w WinAVR ;-)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Polish to

Threaded View
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();
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

Re: Problem lekko OT, ale w WinAVR ;-)
Grzegorz Kurczyk pisze:

Quoted text here. Click to load it

można krócej:

tRect r = ;
    Rysuj(r);

Quoted text here. Click to load it

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

--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Quoted text here. Click to load it

Przyszło mi jeszcze do głowy makro:

#define RECT(__a,__b,__c,__d)    ({static const tRect __r =
; __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,
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
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


Re: Problem lekko OT, ale w WinAVR ;-)
On Thu, 11 Jun 2009 16:16:54 +0200,  Grzegorz Kurczyk wrote:
Quoted text here. Click to load it

Nie wysilaj sie, wez lepszy procek :-)

Quoted text here. Click to load it

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.


Re: Problem lekko OT, ale w WinAVR ;-)
Użytkownik J.F. napisał:
Quoted text here. Click to load it

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

Re: Problem lekko OT, ale w WinAVR ;-)
Grzegorz Kurczyk pisze:

Quoted text here. Click to load it

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,
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Zbych pisze:

Quoted text here. Click to load it

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 /

We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Adam Dybkowski pisze:

Quoted text here. Click to load it

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,
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Zbych pisze:

Quoted text here. Click to load it

A cóż to za wymaganie? 1uA to pobiera dobry RTC a nie mikrokontroler.

AVRy mają prąd upływu do 1uA na każdy pin I/O (patrzę w PDFa pierwszej z
brzegu ATmegi 128) plus dodatkowo typowo 5uA (max. 10uA) w najgłębszym
power-down i to przy wyłączonym watchdogu. Oprócz tego każdy obciążony
pull-up zjada nieco prądu (typowa rezystancja to 20-50 kOhm). Daleko
stąd raczej do magicznego 1uA.

Jak chcesz oszczędzać prąd to bierz się raczej za rodzinę MSP430 a nie AVRy.

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

We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Quoted text here. Click to load it

Zobacz np. ATMega48PA/88PA/168PA/328PA. W uspieniu prad 0,8 mikroA. Przy
normalnym dzialaniu z zegarem 20MHz prad 2-3mA. ARMy sie do tego nawet
nie zblizaja.

--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
Adam Dybkowski pisze:
Quoted text here. Click to load it

To chyba nie jest wygórowane wymaganie dla _wyłączonego_ uC (ale
potrafiącego się wybudzić po zmianie stanu portów)? STM32 prawie by się
łapał, gdy nie to, że prąd w nim rośnie ze wzrostem temperatury.

Quoted text here. Click to load it


Spokojnie, nie tylko TI robi takie wynalazki. Atmel ma uC "pico-power",
Microchip "nono-watt".
Poza tym za 10zł dostaniesz najmniejszego MSP430 (4kB flash, 256B Ram).
Za podobne pieniądze mam ATmega324p, która spełnia moje wymagania co do
poboru prądu (i ma potrzebne peryferia). Zresztą jaką mam gwarancję, że
gcc będzie generowało lepszy kod na msp430 niż na avr?
(pamiętasz? polecałeś ARMa ze względu na lepsze wsparcie w gcc). Ruch na
liście mailingowej msp430-gcc jest raczej znikomy. Kolejna rzecz, to
zakres napięć zasilających. AVR mogę zasilić prosto z li-ion. Do MSP430
musiałbym dodać stabilizator (który też żre prąd na swoje potrzeby).

Re: Problem lekko OT, ale w WinAVR ;-)
Quoted text here. Click to load it

Cos Zbych przesadza. Tak sobie patrze w swoje programy i tez na AVR gcc
ladnie optymalizuje. Czasami pobieznie patrzac na kod wydaje sie, ze
mozna by cos zrobic lepiej, ale przy dokladniejszym spojrzeniu okazuje
sie, ze jednak nie.


--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
T.M.F. pisze:
Quoted text here. Click to load it

Nie przesadza, wystarczy sprawdzić.

--
przeciez moje rozumowanie bylo bez skazy,
no sam bym wskoczyl do tego wulkanu,
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
W dniu 11.06.2009 15:02, Zbych pisze:
Quoted text here. Click to load it

No zagladam dosyc czesto przy okazji debuggowania tego co napisalem.
Jakis koszmarnych brakow optymalizacji nie zauwazylem. Mozesz podac
konkretny przyklad w C, ktory jest zle optymalizowany? To zawsze mozna
zglosic jako bug.

--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
T.M.F. pisze:

Quoted text here. Click to load it

To zależy co kto uważa za koszmarne. Poniżej parę przykładów, ale
wątpię, żeby komuś chciało się to czytać.

Wszystkie przykłady były optymalizowane na rozmiar.


---------------------------------------------------------
Testowanie warunków logicznych:

#define PIN1_IS_LOW    (!(PINB & (1<<PINB7)))
#define PIN2_IS_LOW    (!(PINB & (1<<PINB6)))
    
    volatile uint8_t a;
    asm volatile(";start");
    a = (PIN1_IS_LOW || PIN2_IS_LOW);
    asm volatile(";stop");

Kod wynikowy:

  32                       ;start
   33                    ;  0 "" 2
   34                   .LSM2:
   35                   /* #NOAPP */
   36 000a 1F99              sbic 35-32,7
   37 000c 00C0              rjmp .L2
   38 000e 81E0              ldi r24,lo8(1)
   39 0010 90E0              ldi r25,hi8(1)
   40 0012 00C0              rjmp .L3
   41                   .L2:
   42 0014 83B1              in r24,35-32
   43 0016 90E0              ldi r25,lo8(0)
   44 0018 26E0              ldi r18,6
   45 001a 9695          1:    lsr r25
   46 001c 8795              ror r24
   47 001e 2A95              dec r18
   48 0020 01F4              brne 1b
   49 0022 8095              com r24
   50 0024 9095              com r25
   51 0026 8170              andi r24,lo8(1)
   52 0028 9070              andi r25,hi8(1)
   53                   .L3:
   54 002a 8983              std Y+1,r24
   55                   .LVL0:
   56                   .LSM3:
   57                   /* #APP */
   58                    ;  96 "main.c" 1
   59                       ;stop

Pomijając już tą nieszczęsną promocję do inta, to najbardziej w tym
kodzie rozwaliło mnie wyłuskiwanie 6 bitu.

Delikatna modyfikacja kodu:

    if (PIN1_IS_LOW || PIN2_IS_LOW)    a = true;
    else a = false;


daje już coś takiego:

   62                   /* #NOAPP */
   63 002c 1F9B              sbis 35-32,7
   64 002e 00C0              rjmp .L4
   65 0030 1E99              sbic 35-32,6
   66 0032 00C0              rjmp .L5
   67                   .L4:
   68 0034 81E0              ldi r24,lo8(1)
   69 0036 8983              std Y+1,r24
   70                   .LVL1:
   71 0038 00C0              rjmp .L6
   72                   .L5:
   73                   .LSM5:
   74 003a 1982              std Y+1,__zero_reg__
   75                   .LVL2:
   76                   .L6:


----------------------------------------------------------
Przygotowanie ramki na stosie dla 5 parametrów 16-bitowych:

  1637 0068 ADB7              in r26,__SP_L__
  1638 006a BEB7              in r27,__SP_H__
  1639 006c 1A97              sbiw r26,10
  1640 006e 0FB6              in __tmp_reg__,__SREG__
  1641 0070 F894              cli
  1642 0072 BEBF              out __SP_H__,r27
  1643 0074 0FBE              out __SREG__,__tmp_reg__
  1644 0076 ADBF              out __SP_L__,r26

Przy dwóch parametrach:

  1751 010e 00D0              rcall .
  1752 0110 00D0              rcall .

Łatwo policzyć, że poniżej 8 parametrów bardziej opłaca się wersja z
rcall (program optymalizowany na rozmiar).



-----------------------------------------------------------
Adresowanie struktur i pobieranie adresów z flasha:

typedef struct{
    const prog_char * a;
    const prog_char * b;
    const prog_char * c;
    const prog_char * d;
}Aqq;

prog_char s[] = "Aqq";

Aqq PROGMEM tab[]={
    ,
    ,
    ,
    ,
};

    asm volatile (";start");
    for (uint8_t i = 0; i < tab_size(tab); i++){
        blabla( pgm_read_word( &tab[i].a ), pgm_read_word( &tab[i].b ),
pgm_read_word( &tab[i].c ), pgm_read_word( &tab[i].d ) );
    }
    asm volatile (";stop");


Pierwszy problem to wyliczanie adresu w flashu:

   69                   .LBB24:
   70 0024 F901              movw r30,r18
   71                   .LVL4:
   72 0026 E050              subi r30,lo8(-(tab+4))
   73 0028 F040              sbci r31,hi8(-(tab+4))
   74                   /* #APP */
   75                    ;  106 "main.c" 1
   76 002a 4591              lpm r20, Z+
   77 002c 5491              lpm r21, Z
   78                       
   79                    ;  0 "" 2

Pomimo, że jest (czy raczej mogłoby być) użyte adresowanie z
postinkrementacją, to adresy kolejnych elementów są i tak przed każdym
pobraniem na nowo wyliczane. W przykładzie, który podałem daje to 12
niepotrzebnych instrukcji w każdym obiegu tej krótkiej pętli i dodatkowo
zajętą parę rejestrów R19:R18.

Drugi problem, to wyliczanie od początku adresu komórki w tablicy przy
każdym obiegu pętli:

   27                       ;start
   28                    ;  0 "" 2
   29                   /* #NOAPP */
   30 0000 C0E0              ldi r28,lo8(0)
   31 0002 D0E0              ldi r29,hi8(0)
   32                   .L2:
   33                   .LBB21:
   34                   .LBB22:
   35                   .LSM2:
   36 0004 9E01              movw r18,r28
   37 0006 83E0              ldi r24,3
   38 0008 220F          1:    lsl r18
   39 000a 331F              rol r19
   40 000c 8A95              dec r24
   41 000e 01F4              brne 1b
   42 0010 F901              movw r30,r18
   43                   .LVL0:

[...]

   96                   .LBE25:
   97 0038 0E94 0000         call blabla
   98                   .LVL8:
   99 003c 2196              adiw r28,1
  100                   .LSM3:
  101 003e C430              cpi r28,4
  102 0040 D105              cpc r29,__zero_reg__
  103 0042 01F4              brne .L2
  104                   .LBE21:
  105                   .LSM4:
  106                   /* #APP */
  107                    ;  108 "main.c" 1
  108                       ;stop


Wystarczy prosty myk ze wskaźnikiem i pętla się skraca:

    asm volatile (";start");
    for (uint8_t i = 0; i < tab_size(tab); i++){
        const Aqq * p = &tab[i];
        blabla( pgm_read_word( &p->a ), pgm_read_word( &p->b ), pgm_read_word(
&p->c ), pgm_read_word( &p->d ) );
    }
    asm volatile (";stop");


  27                       ;start
   28                    ;  0 "" 2
   29                   /* #NOAPP */
   30 0000 C0E0              ldi r28,lo8(tab)
   31 0002 D0E0              ldi r29,hi8(tab)

[...]

   87 0022 0E94 0000         call blabla
   88                   .LVL8:
   89 0026 2896              adiw r28,8
   90                   .LBE23:
   91                   .LSM3:
   92 0028 80E0              ldi r24,hi8(tab+32)
   93 002a C030              cpi r28,lo8(tab+32)
   94 002c D807              cpc r29,r24
   95 002e 01F4              brne .L2
   96                   .LBE22:
   97                   .LSM4:
   98                   /* #APP */
   99                    ;  109 "main.c" 1
  100                       ;stop
  1

A podobno gcc ma super optymalizator do pętli (widocznie moja wersja
gdzieś go zgubiła).

Re: Problem lekko OT, ale w WinAVR ;-)
Użytkownik Zbych napisał:
Quoted text here. Click to load it

Ooooo to, to :-) W programach unikam operacji logicznych na bitach
portów, bo wychodzą koszmarki. Czasem zamiast:

if((PINB & (1<<7)) && (PINC & (1<<3)))

lepiej napisać

if(PINB & (1<<7))
   if(PINC & (1<<3))
    

Z jakiś troszkę wcześniejszych wersji pamiętam, że samo wstawienie
operatora ! na bicie portu automatycznie generowało koszmarek z rozkazem
in i wyliczaniem stanu bitu na piechotę.

if(PINB & (1<<7)) wyglądało poprawnie z użyciem sbic/sbis,
ale już:
if(!(PINB & (1<<7))) generowało wspomniany przez Kolegę koszmarek
i w zastępstwie używałem:
if(PINB & (1<<7)) else i juz było cacy na sbic/sbis

Co do adresowania tablic w pamięci FLASH w pętli to już od dawna stosuję
wyłącznie inkrementację wskaźnika, bo te każdorazowe wyliczanie adresu
też mnie biło w oczy :-)

P.S. Używam trochę starawej wersji 20070525, bo sprawia mi najmniej
problemów. Późniejsze wersje 2008xxxx sprawiły mi zbyt dużo psikusów i
trochę się zraziłem. Choć może warto wypróbować jakąś świeżynkę :-)

Pozdrawiam
Grzegorz

Re: Problem lekko OT, ale w WinAVR ;-)
Quoted text here. Click to load it

To się mocno zmieniło w nowszych wersjach gcc. W wielu przypadkach to
się kompiluje do cbi/sbi. Z kolei ja ostatnio używam wyłącznie C++, więc
niewykluczone, że są tu pewne różnice w optymalizacji.
Inna sprawa, że jesli pisze program skladający się z kilku tysięcy linii
to wielu przypadkach efektywność generowanego kodu mnie nie interesuje.
A jesli mam miejsca czasowo krytyczne to zawsze mam inline assembler.


--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
W dniu 12.06.2009 03:54, Zbych pisze:
Quoted text here. Click to load it

Promocja do int wynika ze standardu C wiec trudno tu robić zarzut
kompilatorowi. Żeby to ominąć wystarczy explicite typecastowac.

Quoted text here. Click to load it

Tu faktycznie jest jakiś problem z optymalizacja. Warto to zgłosić jako Bug.

Quoted text here. Click to load it

Tu sprawa nie jest tak oczywista. Co prawda rcall są krótsze w sensie
długości kodu, ale zajmuja 3 takty zegara. To co generuje gcc zajmuje
niezależnie od długości ramki 9 taktow, czyli 3 rcall. Sytuacja wyglada
jeszcze gorzej kiedy PC jest 22 bitowy – wtedy 4 takty. Wiec jak sadze
wybrano pewien kompromis pomiedzy długością kodu a czasem egzekucji.

Quoted text here. Click to load it

To zalezy zapewne od zdefiniowanej przez ciebie funkcji tab_size(tab).
Kompilator za każdym obiegiem petli musi ja wywołać, żeby wilczyć wynik
dla danego argumentu – dlaczego? Bo ja źle zdefiniowałeś.

Quoted text here. Click to load it

Sprawdziłem to u siebie i nic takiego się nie dzieje. Musiałem
zdefiniować dodatkowo dziwna funkcje Babla bo mi kompilator to
optymalizował i ją wywalał.

Quoted text here. Click to load it

Tu problem jest bardziej dyskretny. C przy adresowaniu elementĂłw
struktury używa adresowania z przemieszczeniem. W pierwszym przykładzie
pobierasz adresy konkretnego elementu, stad za każdym razem są pobierane
pełne adresy. Za drugim razem używasz adresu struktury i offsetów do jej
elementĂłw (operator -> generuje offsety). ZauwaĹź, Ĺźe gdyby pola tej
struktury były duże – powyżej 127 bajtów, to i tak zaszłaby konieczność
pobrania pełnego adresu, bo offset byłby większy niż maksymalne
przemieszczenie. Oczywiście kompilator może sobie z tym poradzić,
niestety tu wychodzi jedna z wad gcc – jest to kompilator pod duże
procki, a AVR jest tylko specyficzną wspieraną platformą. Żeby ta
optymalizacja dobrze zadziałała trzebaby nieźle zamieszać w kodzie gcc.
A w sumie jeśli często się ogląda sesje typu połączony C+assembler to
człowiek szybko się uczy jaka składnia języka jest optymalna. Akurat
przy pętlach ze względu na specyfikę listy rozkazów AVR można się nieźle
wykazać.

Quoted text here. Click to load it

Jak ci nie pasuje gcc to zaproponuj cos lepszego... nie mowiac juz o
tym, ze masz kod źródłowy wiec możesz się wykazać dla potomności :)

--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
We've slightly trimmed the long signature. Click to see the full one.
Re: Problem lekko OT, ale w WinAVR ;-)
T.M.F. pisze:

Quoted text here. Click to load it

Wyraźnie napisałem, że nie promocja jest tu największym problemem.
Zresztą rzutowanie i tak tego nie poprawia.

Quoted text here. Click to load it

Specjalnie napisałem, że optymalizacja była ustawiona na rozmiar, więc
rcall powinno mieć pierwszeństwo.

Quoted text here. Click to load it

Zapomniałem wstawić. Oto kod:

#define tab_size(__a)    (sizeof(__a)/sizeof(__a[0]))

Jeśli według ciebie jest źle zdefiniowana, to czekam na poprawki.

Quoted text here. Click to load it

Ja na potrzeby przykładu w ogóle jej nie zdefiniowałem (nie jest to
potrzebne, disasemblację zrobiłem po kompilacji, bez linkowania).

Quoted text here. Click to load it

Chciałeś przykłady, to ci je pokazałem. Nie jest w tym przypadku istotne
czy inne kompilatory zrobiłyby to lepiej (a myślę, że IAR byłby lepszy).

Quoted text here. Click to load it

Dzięki, już kiedyś próbowałem (na innym porcie gcc). To nie jest robota
na 1 dzień, a ja mam swoją pracę.

Site Timeline