Aktyw Forum
Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.
Sprawdź punkty Zarejestruj sięopóźnienie - ale jak
Moderatorzy:Jacek Bogusz, robertw, k.pawliczak, Moderatorzy
Witam
mam takie pytanie
jak w asemblerze dla 89c4051 zrobić wstawke która nic nie robi tylko odczekuje powiedzmy okolo sekundy
w bascomie dość często zmuszony jestem do korzystania z instrukcji wait lub waitms a każda z nich zabiera 4 bajty
i chodzi mi o to aby instrukcje tą zamienić na jakaś wstawkę asemblerową tak aby zajmowała mniej instrukcja nie musi opóźniać dokładnie o 1 sekundę - może o pół albo o dwie jak - czy ktoś coś podpowie ????
mam takie pytanie
jak w asemblerze dla 89c4051 zrobić wstawke która nic nie robi tylko odczekuje powiedzmy okolo sekundy
w bascomie dość często zmuszony jestem do korzystania z instrukcji wait lub waitms a każda z nich zabiera 4 bajty
i chodzi mi o to aby instrukcje tą zamienić na jakaś wstawkę asemblerową tak aby zajmowała mniej instrukcja nie musi opóźniać dokładnie o 1 sekundę - może o pół albo o dwie jak - czy ktoś coś podpowie ????
Utwórz sobie podprogram, w którym będzie tylko instrukcja Wait:
To jest najprostrze rozwiązanie. Niezależnie czy opóźniewnie będzie w basicu czy asemblerze, to będziesz się do niego odwoływał przez "call".
Kod: Zaznacz cały
Declare Sub MyWait
'*** Code ***
instr1
instr2
call MyWait - 2 bajty
instr3
'************
Sub MyWait
Wait 1
End Sub
hmm w polskim helpie stoi jak byk - 4 bajtyWitam.
Mylisz się pisząc, że waitms lub wait zajmuje 4 bajty. Te instrukcje po prostu wywołują odpowiedni podprogram w asemblerze, gdzie sam podprogram zajmuje więcej miejsca.
teedd
mało tego - sprawdziłem empirycznie juz dawno temu ze zajmuje to 4 bajty
nie wiem jak jest z dłuższymi wartościami - ale przeważnie używam około 3 sekund
p.s.
właśnie sprawdziłem - waitms zajmuje więcej bo 22 bajty
co do wait zajmuje 4 bajty jak pisałem wyżej niezależnie czy to wait 1 czy wait 1000
no więc tak - mówisz i masz - jeżeli masz bascoma to sam sprawdź a jezeli nie - to jak nie uwierzysz to trudno.........................CIACH................................
Jesli ktokolwiek jest innego zdania, prosze mnie oswiecic, bo jak Tomasz: nie uwierze poki nie zobacze.
obejrzyj ten sam kod z małą modyfikacją "wait 100" oraz wyniki po kompilacji
Ok jezeli masz coś do dodania to czekam z niecierpliwością
Nie mam... teraz to nie mam zadnego srodowiska ;/ ale to sie niedlugo zmieni.no więc tak - mówisz i masz - jeżeli masz bascoma to sam sprawdź a jezeli nie - to jak nie uwierzysz to trudno
Nie rozumiesz... to jest niemozliwe by to zrealizowac, bascom widocznie wykozystuje tu jakas procedurka ktora tak czy siak umieszcza w kodzie, te 4 bajty ktore przybywaja to jest prawdopodobnie jedynie call do tej procedury, nie zas inplementacja wait'a.
Tak wiec Twoj pokaz dalej mnie nie przekonuje, poprosze o implementacje takiego rozwiazania w ASM, badz kodzie
Nie mam nic do dodania - posta napisalem bo szukam pomocy a nie po to żeby komuś coś udowadniać
(Choć to co napisałeś ma jakiś sens jednak znaczyłoby ze jest umieszczana zawsze jakas procedura odliczająca niezależnie czy używamy wait czy nie)
-nie wierzysz Twoja sprawa jak zmienisz środowisko to sam popatrz
skoro jednak nikt nie ma nic ciekawszego do dodania to temat uważam za zamknięty
(Choć to co napisałeś ma jakiś sens jednak znaczyłoby ze jest umieszczana zawsze jakas procedura odliczająca niezależnie czy używamy wait czy nie)
-nie wierzysz Twoja sprawa jak zmienisz środowisko to sam popatrz
skoro jednak nikt nie ma nic ciekawszego do dodania to temat uważam za zamknięty
Mały eksperyment :
Disasemblacja kodu (bo oczywiście Bascom skrzętnie ukrywa owoce swojej pracy):
Główna pętla programu wygląda następujaco :
Procedura opóźniająca znajduje się pod etykietą X0039 i wywołuje dwie dodatkowe procedury, co przedstawione jest poniżej :
Te cztery bajty to tylko instrukcje :
Ile bajtów zajmują procedury opóźniajace nie chce mi sie liczyć.
-> rdt, skompiluj program
oraz
i wtedy porównaj rozmiar generowanego kodu. Bo na podstawie screenów które zamieściłeś takich wniosków wyciągnąć nie można z bardzo prostej przyczyny : w programie korzystasz z procedur obsługi LCD, a one też korzystają z opóźnień, tak więc dodanie instrukcji wait powoduje umieszczenie tylko ich wywołania bo ich kod jest używany przez procedury LCD.
Kod: Zaznacz cały
do
wait 1
loop
end
Główna pętla programu wygląda następujaco :
Kod: Zaznacz cały
X0051: mov r0,#7fh;\
clr a ;|
X0054: mov @r0,a ;| czyszczenie wewnętrznej pamięci ram
djnz r0,X0054 ;/
mov sp,#21h ;inicjalizacja wskaźnika stosu
mov 20h,#0 ; wyzerowanie bitu ERR
X005d: mov r0,#1 ; czas opóźnienia
acall X0039 ; wywołanie procedury opóźniającej
ljmp X005d ; pętla nieskończona
Kod: Zaznacz cały
X002e: push acc
mov a,#1bh
X0032: dec a
jnz X0032
pop acc
nop
ret
;
X0039: mov a,#0c8h
X003b: acall X0045
acall X0045
djnz acc,X003b
djnz r0,X0039
ret
;
X0045: push acc
mov a,#19h
X0049: acall X002e
dec a
jnz X0049
pop acc
ret
;
Kod: Zaznacz cały
X005d: mov r0,#1 ; czas opóźnienia
acall X0039 ; wywołanie procedury opóźniającej
-> rdt, skompiluj program
Kod: Zaznacz cały
do
wait 1
loop
end
Kod: Zaznacz cały
do
loop
end
W to juz jestem w stanie uwierzyc na slowoRadziu - zrobiłem jak mi pokazales - roznica to okolo 40 bajtów
Rdt: jak widac Ty rowniez nie czytasz tego co sie Ci odpowiada. Wiec moze odpowiem tak:
Komorka mi siada... mozesz mi polecic jakas baterie, zeby miescila sie w miejsce oryginalnej, ale trzymala tak z rok ?? no, ostatecznie moze byc pol roku intensywnego korzystania.
[ Dodano: 20-03-2007, 10:37 ]
Wybaczcie post pod postem, ale chcialem odswiezyc temat, troche pomyslalem i jeszcze cos mi przyszlo do glowy, skoro tak koniecznie chcesz odchudzic program:
Moglbys odchudzic wywolanie waita do 2 bajtow, ale... no wlasnie, stosujac samo acall X0039, tyle ze wowczas podejmujesz spore (i moim zdaniem nigdy nie akceptowalne) ryzyko... jakie, ano takie ze nie masz wplywu na to ile to opoznienie bedzie trwalo, bo to bedzie odpowiednik wait 1 -- wait 256 (256 - to nie pomylka, dobrze ze wait przyjmuje tylko 1 bajt ), a zalezec bedzie od aktualnej wartosc r0.
Czy Ci sie to oplaca, i ile tak naprawde masz tych wywolan by tak walczyc o kazde 2 bajty ?? ocen to sam.
Oczywiscie nie jest to sprzeczne z tym co pisalem wczesniej, nie da sie zrobic opoznienia w mniej niz 4 bajtach (nawet w 4 to z duzymi ograniczeniami), to jest jedynie wykozystanie faktu ze ten wait jest juz gdzies przez Ciebie (bascom) dolinkowanyę przez jakas inna biblioteke (LCD ??).
Ostatnio zmieniony 20 mar 2007, o 10:45 przez pajaczek, łącznie zmieniany 2 razy.
-
- -
- Posty:2
- Rejestracja:8 cze 2005, o 11:07
- Lokalizacja:Winny Grod
Można "zużyć" 2 bajty i mieć pewność , że w R0 będzie 1...Moglbys odchudzic wywolanie waita do 2 bajtow, ale... no wlasnie, stosujac samo acall X0039, tyle ze wowczas podejmujesz spore (i moim zdaniem nigdy nie akceptowalne) ryzyko... jakie, ano takie ze nie masz wplywu na to ile to opoznienie bedzie trwalo, bo to bedzie odpowiednik wait 1 -- wait 256 (256 - to nie pomylka, dobrze ze wait przyjmuje tylko 1 bajt ), a zalezec bedzie od aktualnej wartosc r0. ...
Warunek , wszystkie wywołania funkcji opóźniającej , muszą znajdować się na tej samej stronie pamięci , co owa funkcja/procedura.
Kod: Zaznacz cały
Do
Gosub Jednasekunda ' zajętość pamięci programu , to 2 bajty dla gosub i ...
Gosub Jednasekunda '... czas wykonania , to Wait 1 + 4 cykle maszynowe.
Gosub Jednasekunda
Gosub Jednasekunda
Gosub Jednasekunda
Gosub Jednasekunda
Gosub Jednasekunda
Loop
Jednasekunda:
Wait 1
Return
Piotrek
No sprytnie sprytnie, tyle ze tez nie do konca . 2 bajty zajmie gosub, zas wait 1 + return kolejne 6Można "zużyć" 2 bajty i mieć pewność , że w R0 będzie 1
Warunek , wszystkie wywołania funkcji opóźniającej , muszą znajdować się na tej samej stronie pamięci , co owa funkcja/procedura.
A wiec calosc zajmie
Kod: Zaznacz cały
N*2 + 6
B = -------
N
gdzie: N - ile razy uzyto opoznienia
B - liczba bajtow przypadajaca na 1 wywolanie
A to jedynie asymptotycznie zbliza sie do 2B / kazde wywolanie.
Ok - widzę ze tutaj nie ma zbytnio z czego zabrać
jeżeli więc możecie to powiedzcie mi inną rzecz - jak w asemblerze zabrać bajt spod jednego adresu i wsadzić pod drugi adres
odpowiedniki instrukcji peek i poke
może tutaj mi sie uda zaoszczędzić te parę bajtów
jeżeli w ogóle macie parę rad dotyczących optymalizacji kodu to chętnie posłucham
jeżeli więc możecie to powiedzcie mi inną rzecz - jak w asemblerze zabrać bajt spod jednego adresu i wsadzić pod drugi adres
odpowiedniki instrukcji peek i poke
może tutaj mi sie uda zaoszczędzić te parę bajtów
jeżeli w ogóle macie parę rad dotyczących optymalizacji kodu to chętnie posłucham
Witam Chłopaki!
Bawiłem sie kiedyś bascomem i wiem że można zrobić wstawke asambler w programie. Wy tu próbujecie kożystać z poleceń bascoma a on tylko wykożystuje odpowiednie podprogramy napisane w asamblerze i zajmuje to kilka a nawet kilkadziesiąt bajtów. Wyszukaj sobie w helpie jak zrobić wstawkę asamblera...
z tego co pamietam to było chyba $asm
A potem wstaw taki kawałek programu napisanego najprościej w asamblerze:
MOV R2,#1
TIME:
DJNZ R0,$
DJNZ R1,TIME
DJNZ R2,TIME
programik realizuje odliczanie na rejestrach w pamieci ram dokładny czas tej operacji wynosi 0,524288 sekundy dla kwarcu 12MHz wszystkie instrukcje zajmują 8 bajtów i mniej sie nie da bo asambler to najprostszy jezyk programowania i nie wykożystuje podprogramów jak to robi bascom. Poszczególne rejestry są odliczane w kierunku zera jak skończy to program poleci dalej. Zeby zmienić czas trzeba załadowac do rejestrów odpowiednie wartości, w tym wypadku do R2 wprowadziłem wartość 1 czyli czas opóźnienia wynosi około 0,5s jej zwiekszysz tą wartość to czas proporcjonalnie sie zwiekszy. Na końcu tego programu musisz wstawić polecenie kończące wstawkę asamblera ale nie wiem jakie to jest, bedzie napisane w helpie do bacoma przy poleceniu wstawki. Aha żeby użyć tej wstawki musisz dokładnie wiedzieć z których rejestrów kożysta bacom ponieważ mogą one zostać zmienione przez ta wstawke gdyż ona odnosi sie do rejestrów o adresah 00h, 01h, 02h ( odpowiednio R0, R1, R2).
Powodzenia
Bawiłem sie kiedyś bascomem i wiem że można zrobić wstawke asambler w programie. Wy tu próbujecie kożystać z poleceń bascoma a on tylko wykożystuje odpowiednie podprogramy napisane w asamblerze i zajmuje to kilka a nawet kilkadziesiąt bajtów. Wyszukaj sobie w helpie jak zrobić wstawkę asamblera...
z tego co pamietam to było chyba $asm
A potem wstaw taki kawałek programu napisanego najprościej w asamblerze:
MOV R2,#1
TIME:
DJNZ R0,$
DJNZ R1,TIME
DJNZ R2,TIME
programik realizuje odliczanie na rejestrach w pamieci ram dokładny czas tej operacji wynosi 0,524288 sekundy dla kwarcu 12MHz wszystkie instrukcje zajmują 8 bajtów i mniej sie nie da bo asambler to najprostszy jezyk programowania i nie wykożystuje podprogramów jak to robi bascom. Poszczególne rejestry są odliczane w kierunku zera jak skończy to program poleci dalej. Zeby zmienić czas trzeba załadowac do rejestrów odpowiednie wartości, w tym wypadku do R2 wprowadziłem wartość 1 czyli czas opóźnienia wynosi około 0,5s jej zwiekszysz tą wartość to czas proporcjonalnie sie zwiekszy. Na końcu tego programu musisz wstawić polecenie kończące wstawkę asamblera ale nie wiem jakie to jest, bedzie napisane w helpie do bacoma przy poleceniu wstawki. Aha żeby użyć tej wstawki musisz dokładnie wiedzieć z których rejestrów kożysta bacom ponieważ mogą one zostać zmienione przez ta wstawke gdyż ona odnosi sie do rejestrów o adresah 00h, 01h, 02h ( odpowiednio R0, R1, R2).
Powodzenia
Kod: Zaznacz cały
Dim Variable1 As Byte
Dim Variable2 As Byte
$asm
'wersja na stałych
mov r0, #&h30 'załaduj do wskaźnika r0 adres stałej = 30 hex (przykładowo)
mov a, @r0 'przenieś do akumulatora (można w nim dowolnie tą daną zmienić)
mov r0, #&h31 'załaduj do wskaźnika r0 adres docelowy (stała)
mov @r0, a 'zapisz pod adresem r0 = 31 hex zmienną z akumulatora
'wersja na zmiennych
mov r0, #{variable1} 'załaduj do wskaźnika adres zmiennej (NIE wartość, którą przechowuje)
mov a, @r0 'przenieś do akumulatora (można w nim dowolnie tą daną zmienić)
mov r0, #{variable2} 'załaduj do wskaźnika r0 adres docelowy (zmiennej Variable2)
mov @r0, a 'zapisz pod adresem r0 zmienną z akumulatora
$end Asm
Co prawda "specjalistą" jestem bardziej od AVR'ów, ale w razie czego mogę pomóc w czymś jeszcze.
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 21 gości