Witam,
Poniżej zamieszczam fragment programu w assemblerze dla mikrokontrolera Atmel AVR ATmega32. Byłbym wdzięczny za zapoznanie się z nim i moim komentarzem i odpowiedź, czy dobrze rozumuję.
int main(void) { 8e: cf e5 ldi r28, 0x5F ; 95 90: d4 e0 ldi r29, 0x04 ; 4 92: de bf out 0x3e, r29 ; 62 94: cd bf out 0x3d, r28 ; 61
PORTB = _BV(PB1); 96: 82 e0 ldi r24, 0x02 ; 2 98: 88 bb out 0x18, r24 ; 24
PORTB |= _BV(PB1); 9a: c1 9a sbi 0x18, 1 ; 24
sbi(PORTB, PB1); 9c: c1 9a sbi 0x18, 1 ; 24
*** PORTB |= _BV(PB1) jest tożsame z sbi(PORTB,PB1);PORTB |= _BV(PB1) | _BV(PB2); 9e: 88 b3 in r24, 0x18 ; 24 a0: 86 60 ori r24, 0x06 ; 6 a2: 88 bb out 0x18, r24 ; 24
*** Jeżeli za pomocą PORTB |= ... chcemy ustawić więcej niż jeden bit, to najpierw pobierana jest "wartość" występująca na tym porcie, następnie wykonywana jest na tej wartości operacja alternatywy z maską określającą bity, które mają zostać ustawione, a następnie uzyskany wynik zapisywany jest do portu. Załóżmy, że w głównej pętli programu ustawiamy/zerujemy wyjścia na jakimś porcie za pomocą PORTB |= _BV(PB1) | _BV(PB2). W programie działa funkcja obsługi przerwania, która także operuje na PORTB. Zatem może pojawić się sytuacja, w której w programie głównym zostanie odczytana "wartość" na porcie (in r24, 0x18), następnie zacznie być wykonywana funkcja obsługi przerwania, która zmieni wartość na PORTB, po czym nastąpi powrót do programu głównego i wykonanie ori r24,0x06 out 0x18,r24 -- z tym że ori r24,0x06 zostanie wykonana na wartości portu, która była uprzednio (przed wejściem do funkcji obsługi przerwania). Stąd, może pojawić się pewne zamieszanie i program może działać niepoprawnie. Czy dobrze myślę?Z góry dziękuję za pomoc. Robbo