Jak zrobic w Keilu C tablice adresow funkcji ? Funkcje sa od siebie niezalezne (nie wywoluja siebie). Poniewaz kompilator zaklada, ze funkcje moga sie wywolywac to rezerwuje pamiec oddzielnie dla kazdej funkcji i w ten sposob bardzo szybko konczy sie wewnetrzny ram. Ewentualnie jak napisac jakas oszczedna funkcje, ktora na podstawie parametru wybiera inna funkcje, cos w stylu switch (ale bez niepotrzebnych rozkazow skoku, ktore pozeraja pamiec)
switch(NrFunkcji) { case 1: Funkcja1(); break; case 2: Funkcja2(); break; ... }
Pozd Gissbourne
Didn't find your answer? Ask the community — no account required.
M
marcinuh
Witam.
W manualu C do³±czonym doKeila jest do do¶æ dobrze opisane - nie ró¿ni siê to wiele od normalnego C.
Nie rozumiem - w ramie trzymasz przecie¿ tylko ich adresy (o ile korzystasz z tych wska¼ników), same funkcje znajduj± siê przecie¿ w pamiêci programu...
Je¿eli funkcje maj± ró¿ne typy (ilo¶ci) argumentów mo¿esz je przeci±¿yæ - ale to w sytuacji jakby "odwrotnej" - tablic± wska¼ników do funkcji mo¿esz siê pos³u¿yæ maj±c funkcje zwracaj±ce ten sam typ i przyjmuj±ce te same argumenty - przeci±¿anie opiera siê na przeciwnej zasadzie. pzdr, marcin
M
marcinuh
U¿ytkownik "marcinuh" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:c5lqdq$4b5$ snipped-for-privacy@nemesis.news.tpi.pl...
Ok, juz rozumiem - zamota³em siê ;-) Chodzi Ci o zmienne lokalne a nie o kod przecie¿ :-). pzdr, marcin
G
Gissbourne
U¿ytkownik "marcinuh" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:c5lqdq$4b5$ snipped-for-privacy@nemesis.news.tpi.pl...
W ramie sa zmienne lokalne. Jesli zrobie tablice adresow funkcji to kompilator zaklada, ze moga wzajemnie sie wywolywac czyli wszystkie zmienne umieszcza w roznych komorkach ramu, zeby nie wystapila sytuacja, ze jedna zmienna zamazuje druga. Bez zdefiniowanej tablicy jest normalnie czyli zmienne lokalne roznych funkcji moga wykorzystywac te same komorki.
Mowiac inaczej - powiedzmy, ze mam 100 funkcji (tego samego typu - bez parametrow). Teraz chce napisac funkcje wyboru tych funkcji zaleznie od jakiejs zmiennej. Moge zrobic to za pomoca instrukcji switch i wszystko ok poza rozmiarem. Jesli zrobie wywolywanie za pomoca wskaznika to nie starcza ramu. Pozd Gissbourne
M
Marek Dzwonnik
U¿ytkownik "marcinuh" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:c5lqdq$4b5$ snipped-for-privacy@nemesis.news.tpi.pl
S±dzê, ¿e chodzi o "variable overlaying" czyli lokowanie kilku niezale¿nych zmiennych w tym samym obszarze pamiêci danych. Np. je¿eli wiadomo, ¿e dwie funkcje _na pewno_ nie zostan± wywo³ane jednocze¶nie (nie znajduj± siê w tym samym ³añcuchu odwo³añ) to mo¿na segmenty ich zmiennych lokalnych na³o¿yæ na siebie. W przypadku wywo³ywania funkcji przez tablicê wska¼ników wystêpuj± k³opoty z ustaleniem tych zale¿no¶ci.
Proponujê uwa¿n± lekturê "C51 primera":
formatting link
ile pamiêtam, to istnieje jakie¶ rozwi±zanie (na poziomie dyrektyw linkera) ale na tyle upierdliwe, ¿e kiedy¶ w podobnym przypadku podda³em siê i zarz±dzi³em globalne "NO OVERLAY"
Sorry za brak precyzji, ale piszê z marszu a od dosyæ dawna nie mia³em z tym do czynienia
M
marcinuh
U¿ytkownik "Gissbourne" snipped-for-privacy@poczta.onet.pl> napisa³ w wiadomo¶ci news:c5lrmk$n2j$ snipped-for-privacy@atlantis.news.tpi.pl...
No tu ju¿ siê przyzna³em do zamotania ;-)
Nie wiem, jak wygl±da switch skompilowany na 51, ale ostatnio robi±c do¶æ poka¼ny interpreter poleceñ na PICku doszed³em do wniosku, ¿e nic lepszego mi nie potrzeba. My¶lê, ¿e nie unikniesz kosztów z jednej lub drugiej strony - pewne mechanizmy musz± zaj±æ albo pamiêæ, albo czas - niestety procesor to rodzaj mêski i intuicji nie posiada ;-). pzdr, marcin
J
J.F.
Pomijajac wszystko inne to powinno byc mozliwe zadeklarowanie zainicjowanej tablicy adresow w obszarze programu. cos typu
?PR?A51_EXECUTOR segment CODE ;Deklaracja relokowalnego segmentu dla execute()
RSEG ?PR?A51_EXECUTOR ;Relokowalny segment funkcji 'execute(command)'
; ; EXECUTE ; Funkcja wyboru obs³ugi polecenia sterownika ; Wej¶cie : numer polecenia w rejestrze R7 ; Wyj¶cie : brak ; Uwagi : zastêpuje bardziej efektywnie funkcjê switch(command) napisan± w C51 ; umieszczona w odrêbnym segmencie kodu, dla u³atwienia linkerowi ; analizy wzajemnych odwo³añ funkcji ; powrót z execute() odbywa siê przy pomocy RET wybranej obs³ugi w C51 ; _execute: mov A,R7 ;Obliczenie adresu funkcji obs³ugi w tabeli add A,R7 ;Dwa bajty na AJMP mov DPTR,#jump_table jmp @A+DPTR
Jest to wariant duuuu¿o optymalniejszy ni¿ switch(), wypróbowany w praktyce.
Pzdr,
Marek
M
marcinuh
Nice to by³o, a czy mo¿esz przytoczyæ, jak wygl±da switch skompilowany keilem? Kompilacja dla PICa daje ci±g MOVF parametr (tylko na poczatku switcha) i teraz XORLW (kolejny case) BZ (do adresu z poczatkiem kodu dla danego case) i.t.d.
czyli 2 cykle maszyny na rozpatrzenie kazdego case. pzdr, marcin
M
marcinuh
Przepraszam, 3 cykle - BZ zajmuje dwa cykle, je¿eli w jego wyniku nie jest wykonywany skok... pzdr, marcin
M
Marek
Trochê mi to zajê³o, ale uda³o siê powtórzyæ:
Keil.C
------------------------------------------------------- switch(command) { case 0 : srvc_00(); break; case 1 : srvc_01(); break; case 2 : srvc_02(); break; case 3 : srvc_03(); break; case 4 : srvc_04(); break; case 5 : srvc_05(); break; case 6 : srvc_06(); break; case 7 : srvc_07(); break; case 8 : srvc_08(); break; case 9 : srvc_09(); break; case 10 : srvc_10(); break; case 11 : srvc_11(); break; case 12 : srvc_12(); break; case 13 : srvc_13(); break; case 14 : srvc_14(); break; case 15 : srvc_15(); break; }
MOV A,R7 CJNE A,#010H,?C0219 ?C0219: JC $ + 5H R LJMP ?C0192 R MOV DPTR,#?C0220 MOV R0,A ADD A,R0 ADD A,R0 JMP @A+DPTR ?C0220: R LJMP ?C0196 R LJMP ?C0197 R LJMP ?C0198 R LJMP ?C0199 R LJMP ?C0200 R LJMP ?C0201 R LJMP ?C0202 R LJMP ?C0203 R LJMP ?C0204 R LJMP ?C0205 R LJMP ?C0206 R LJMP ?C0207 R LJMP ?C0208 R LJMP ?C0209 R LJMP ?C0210 R LJMP ?C0211 ; SOURCE LINE # 784 ?C0196: R LCALL srvc_00 SJMP ?C0192 ; SOURCE LINE # 785 ?C0197: R LCALL srvc_01 SJMP ?C0192
--------------------------------------------
Jeszcze tem switch jako tako, ale potem jest LJMP do adresu, spod którego siê dopiero robi lcall ...
Wszystko razem powodowa³o, ¿e ma³ym Atmelku (2051) nie da³o siê ju¿ upchaæ kolejnej funkcji.
Po przej¶ciu na assemblerow± wstawkê dzia³a do dzi¶ efektywnie i niezawodnie ... kto wie, mo¿e nawet ten kod wyprodukowa³ szyneczkê, któr± dzi¶ jad³e¶ na ¶niadanie ? Jest taka mo¿liwo¶æ ;-)
Pzdr,
Marek
M
marcinuh
Hehe, istotnie - jad³em dzi¶ szyneczkê ;-)). Hmm, co¶ mi tu brzydko pachnie - a je¶li za case'ami nie bêd± sta³y kolejne liczby zaczynaj±c od zera?, np:
case 0x11: bleble case 0x73: bleble case 0xAA: bleble ... To wtedy nie bêdziesz móg³ (ani kompilator) po prostu dodac do adresu pocz±tku skoków warto¶ci prze³±cznika... Dobrze kombinujê? Bo czasem nie da siê ustawiæ rozkazów w kolejno¶ci i z drugiej strony nie zawsze pod adresem (adres_pocz_skoków + prze³±cznik) mo¿na co¶ wcisn±æ... I jak wtedy by wygl±da³ taki switch? Bo ten, który przytoczy³e¶, jest cacy ;-). Sorki, je¶li co¶ krêcê i za bardzo wnikam, ale w³a¶nie zauwa¿y³em, ¿e trochê zd±¿y³ mi asm51 ulecieæ ;-). pzdr, marcin
J
J.F.
[...]
W zasadzie musi - przeciez za kazdym razem moglby byc inny zestaw parametrow funkcji. I tak to dosc zgrabnie skompilowal ..
J.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.