logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega162][c][asm] Deasemblacja - rejestr PIN ciekawostka

zagwizdow 18 Cze 2010 11:53 1780 6
  • #1 8202771
    zagwizdow
    Poziom 17  
    Desasemblujac sobie hex'a znalazłem dziwny odczyt rejestrów PINx,
    gdzie kompilator najpierw czytał dwa razy rejestr i później maskował bity/bit w jednym odczycie i potem sprawdzał z drugim odczytem . Ogólnie wygląda jakby wykrywanie 1 (dla pinc) przy braku zmiany pozostałych wejść.
    Ktoś może zetknął się z podobnym kodem ?
    		in	r25,p13
    		in	r24,p13
    		ori	r24,k10
    		cp	r25,r24
    	 brne	L0196
    ;	-----		branch on last line
    		in	r18,p10
    		in	r24,p10
    		ldi	r19,k00
    		ldi	r25,k00
    		andi	r24,kEF
    		cp	r18,r24
    		cpc	r19,r25
    	 brne	L0196
    

    takie cos wykombinowałem z tego :
    	 
    	if (((PINC | 0x10) == PINC) && ((PIND & 0xEF) == PIND))
    


    Dla zwykłego odczytu kompilator daje normalny kod:
    
    uint8_t testowa(void)
    {
    	if (PINE & 0x02) return 1;
    	return 0;
    }

    wynik:
    
     745               	testowa:
     751 027c 85B1      		in r24,37-0x20
     752 027e 9927      		clr r25
     753 0280 9695      		lsr r25
     754 0282 8795      		ror r24
     756 0284 8170      		andi r24,lo8(1)
     757 0286 9070      		andi r25,hi8(1)
     759 0288 0895      		ret
    
  • Pomocny post
    #2 8202881
    elektrofil
    Poziom 17  
    Witaj.
    Jako osoba pisząca w asm to sprawdzanie jest dla mnie przekombinowane, i jest to wynik działania jakiegoś kompilatora, dlaczego? dlatego:

    1) zmiana stanu pinu może nastąpić pomiędzy odczytami portu a po niej jest kilka cykli więc nie chodzi tutaj o pilne i dokładne wykrycie tej zmiany.
    2) analizując zapis można to zrobić o wiele prościej i będzie się szybciej wykonywać:
    - po co ładować dwa rejestry jak w dalszej części programu r25 jest zerowany a do r24 trafia inny odczyt?
    - po co maskować wszystkie bity (z wyjątkiem jednego) a potem porównywać to z innym rejestrem?
    - w r24 może być tylko $00 lub $10 więc pętla czeka aż wartość całego portu nie będzie równa $10

    więc dlaczego nie pobrać zawartości rejestru czyli : in r25,p13
    porównać z $10 : cpi r25,k10
    i wykonać skok do pętli gdy nie równe : brne L0196

    gdyby chodziło o czas wykonania, można dodać NOPy.

    Co do drugiej części programu to dopiero jest galimatias,
    para porównań cp i cpc oraz rozkaz skoku warunkowego za nią jest stosowany w porównaniu liczb 16-sto bitowych lecz tutaj przed tym porównaniem oba starsze bity porównywane są ustawione na $00 więc sensu to nie ma!

    ta część programu sprawdza czy czwarty bit jest równy $00 nie zwracając uwagi na pozostałe bity.
    Nieużywane starsze bajty (załadowywane $00) wskazują iż jest to kolejna "genialna" zaleta kompilatora wyższego poziomu. sam zapis nie szkodzi logicznie programowi, jednak gdy chodzi o objętość kodu i prędkość działania... hmmm... da się to przyśpieszyć o 30% !!!

    Pozdrawiam i życzę sukcesów przy ewentualnym poprawianiu i asemblacji.
  • #3 8203048
    zagwizdow
    Poziom 17  
    Dzieki za odpowiedz, troche uprościłem warunek i tak zostawie . Z ciekawości sprawdziłem na różnych ustawieniach optymalizacji ale nie wygenerowało mi się nic podobnego do tego wcześniejszego.
    if ((PINC & 0x10) && ((PIND & 0x10) == 0))


    Strasznie dziwny odczyt, ciekawe po co ktos takie cos wygenerował bo sprawdzenie dotyczy tylko pinów PINC.4 i PIND.4 a reszta nie ma znaczenia i może tylko bruździć.

    To że na dwóch rejestrach to pewnie dlatego ze kompilator sobie do 16 bitowego rozszerzył ale sensu to nie ma.
  • Pomocny post
    #4 8203115
    szelus
    Poziom 34  
    Rozumiem, że nie masz kodu źródłowego? ;)

    Jako osoba pisząca od wielu lat w C i mająca okazje w tym czasie obejrzeć wiele różnego rodzaju "wynalazków" powiem, że to co napisałeś w pierwszym poście może mieć sens. Tzn. spotkałem się z praktyką pisania kodu testującego flagę bitową w nst. sposób:
    
    if ((zmienna & STALA) == STALA)  // na ustawienie
    
    if ((zmienna | ~STALA) == ~STALA) // na zgaszenie
    


    Teraz wystarczy, że ktoś ubrałby to w makro w rodzaju
    
    #define BIT_IS_SET( x, mask )      ((x & mask) == mask)
    

    a następnie podczas użycia pomylił kolejność argumentów i w połączeniu z volatile dla portów kompilator wygeneruje takie kwiatki.
    Moim zdaniem chodziło o proste sprawdzenie stanu portu (jeżeli z reszty kodu, czy zasady działania nic innego nie wynika).

    poprawiłem literówki i skróty myślowe
  • Pomocny post
    #5 8203122
    elektrofil
    Poziom 17  
    Pomyliłem się!
    A dokładnie ORI potraktowałem jak ANDI
    Pierwsza część sprawdza czy b4 jest ustawiony jeżeli tak to przechodzi dalej
    Druga część sprawdza czy b4 jest skasowany jeżeli tak to przechodzi dalej.

    Przepraszam.

    W pierwszej części wystarczy zrobić PIN ANDI $10 i skoczyć gdy różne od zera.
    W drugiej zrobić PIN ANDI $10 i skoczyć gdy równe zero.

    pozdrawiam.
  • Pomocny post
    #6 8203191
    Konto nie istnieje
    Konto nie istnieje  
  • #7 8203404
    zagwizdow
    Poziom 17  
    Cytat:
    Rozumiem, że nie masz kodu źródłowego?

    Już mam :)
    Tylko ten kawalek dziwnie wygladał i chciałem się upewnic ze dobrze rozumiem o co w nim chodzi a ciekawość jednak dreczyła skąd to sie wzieło co wyjasnił kodem kolega Szelus.
    Dziekuje wszystkim za pomoc.
REKLAMA