Keil C51 - tablica adresow funkcji
Masz problem? Zapytaj na forum elektroda.pl
From: "Gissbourne" <gissbourne_at_nospam_poczta.onet.pl>
Subject: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 12:02:20 +0200
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai
From: "marcinuh" <marcinuh_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 13:05:16 +0200
Witam.
Jak zrobic w Keilu C tablice adresow funkcji ?
W manualu C dołączonym doKeila jest do dość dobrze opisane - nie różni się
to wiele od normalnego C.
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.
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...
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)
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai
From: "marcinuh" <marcinuh_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 13:09:42 +0200
Użytkownik "marcinuh" <marcinuh_at_nospam_wp.pl> napisał w wiadomości
news:c5lqdq$4b5$1_at_nospam_nemesis.news.tpi.pl...
sposob bardzo szybko konczy sie wewnetrzny ram.
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...
Ok, juz rozumiem - zamotałem się ;-) Chodzi Ci o zmienne lokalne a nie o kod
przecież :-).
pzdr,
marcin
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai
From: "Gissbourne" <gissbourne_at_nospam_poczta.onet.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 13:29:04 +0200
Użytkownik "marcinuh" <marcinuh_at_nospam_wp.pl> napisał w wiadomości
news:c5lqdq$4b5$1_at_nospam_nemesis.news.tpi.pl...
Jak zrobic w Keilu C tablice adresow funkcji ?
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...
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!news.nask.pl!news-stoc.telia.net!news-stoa.telia.net!telia.net!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai
From: "marcinuh" <marcinuh_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 14:33:29 +0200
Użytkownik "Gissbourne" <gissbourne_at_nospam_poczta.onet.pl> napisał w wiadomości
news:c5lrmk$n2j$1_at_nospam_atlantis.news.tpi.pl...
W ramie sa zmienne lokalne.
No tu już się przyznałem do zamotania ;-)
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.
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: J.F. <jfox_nospam_at_nospam_poczta.onet.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 17:01:12 +0200
On Thu, 15 Apr 2004 13:29:04 +0200, Gissbourne wrote:
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.
Pomijajac wszystko inne to powinno byc mozliwe zadeklarowanie
zainicjowanej tablicy adresow w obszarze programu.
cos typu
void *(int) PROGMEM tab[]={funcja1, funkcja2,funkcja3}
czy jak to sie tam w keilu zapisuje.
J.
=======
From: "Marek Dzwonnik" <mdz_at_nospam_WIADOMO_PO_CO_TO.message.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 13:38:36 +0200
Użytkownik "marcinuh" <marcinuh_at_nospam_wp.pl> napisał w wiadomości
news:c5lqdq$4b5$1_at_nospam_nemesis.news.tpi.pl
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.
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...
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":
http://www.esacademy.com/automation/docs/c51primer/c51prim.htm
O 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
--
Marek Dzwonnik, GG: #2061027 (zwykle jako 'niewidoczny')
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!news.altec.pl!nobod
From: "Marek" <neticus_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 22:06:46 +0200
Użytkownik "Gissbourne" <gissbourne_at_nospam_poczta.onet.pl> napisał w wiadomości
news:c5lmnp$etr$1_at_nospam_nemesis.news.tpi.pl...
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)
Przykład z życia (zdradzam swój warsztat, niech stracę ... :-) )
Keil.c:
--------
extern void execute(byte);
U8 command;
command = 8;
execute(command);
Keil.asm
----------------------------------------------------------------------------
----------------------------------
;
; Adresy funkcji realizujących obsługę poleceń sterownika nadrzędnego
;
EXTRN CODE (SRVC_00,SRVC_01,SRVC_02,SRVC_03,SRVC_04,SRVC_05,SRVC_06,SRVC_07)
EXTRN CODE (SRVC_08,SRVC_09,SRVC_10,SRVC_11,SRVC_12,SRVC_13,SRVC_14,SRVC_15)
EXTRN CODE (SRVC_16)
?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 _at_nospam_A+DPTR
jump_table: ajmp SRVC_00
ajmp SRVC_01
ajmp SRVC_02
itd ...
ajmp SRVC_16
----------------------------------------------------------------------------
----
Jest to wariant duuuużo optymalniejszy niż switch(), wypróbowany w praktyce.
Pzdr,
Marek
========
Path: news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!not-for-mai
From: "marcinuh" <marcinuh_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 22:16:46 +0200
"Marek" <neticus_at_nospam_wp.pl> wrote in message news:a1qm5c.li7.ln_at_nospam_news.altec.pl...
Użytkownik "Gissbourne" <gissbourne_at_nospam_poczta.onet.pl> napisał w wiadomości
news:c5lmnp$etr$1_at_nospam_nemesis.news.tpi.pl...
[...]
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!news.altec.pl!nobod
From: "Marek" <neticus_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 22:47:32 +0200
Nice to było, a czy możesz przytoczyć, jak wygląda switch skompilowany
keilem?
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;
}
Keil.lst
--------------------------------------------------------
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 _at_nospam_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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!not-for-mai
From: "marcinuh" <marcinuh_at_nospam_wp.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 23:11:53 +0200
"Marek" <neticus_at_nospam_wp.pl> wrote in message news:jdsm5c.q79.ln_at_nospam_news.altec.pl...
i niezawodnie ... kto wie, może nawet ten kod wyprodukował
szyneczkę, którą dziś jadłeś na śniadanie ? Jest taka możliwość ;-)
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
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!not-for-mai
From: J.F. <jfox_nospam_at_nospam_poczta.onet.pl>
Subject: Re: Keil C51 - tablica adresow funkcji
Date: Thu, 15 Apr 2004 23:25:24 +0200
On Thu, 15 Apr 2004 22:47:32 +0200, Marek wrote:
Nice to było, a czy możesz przytoczyć, jak wygląda switch skompilowany
keilem?
switch(command)
{ case 0 : srvc_00(); break;
case 1 : srvc_01(); break;
case 2 : srvc_02(); break;[...]
case 15 : srvc_15(); break;
}
R MOV DPTR,#?C0220
MOV R0,A
ADD A,R0
ADD A,R0
JMP _at_nospam_A+DPTR
?C0220:
R LJMP ?C0196
R LJMP ?C0197
[...]
; 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 ...
W zasadzie musi - przeciez za kazdym razem moglby byc inny zestaw
parametrow funkcji. I tak to dosc zgrabnie skompilowal ..
J.
========
Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mai