Pytanie:
Jak mogę ustawić kod warunku w języku asemblera?
user5140
2012-03-29 18:01:17 UTC
view on stackexchange narkive permalink

Chcę przetestować znak zmiennej. Innymi słowy, chcę znać odpowiedź na pytanie, czy zmienna jest dodatnia czy ujemna. Jak mogę napisać następujące warunki if-then-else w języku asemblera?

  if X > 0 goto A else goto B  

Używam PİC16f87x

Aby moje pytanie było bardziej ogólne, jeśli wiesz, czy możesz udzielić odpowiedzi na poniższe pytania?

i.)

  if X > Y goto A else goto B  

ii.)

  if X > = Y goto A else goto B  

iii.)

  if X! = Y goto A else goto B  
Pamiętam kod asemblera z80, ale porównanie osiąga się przez odejmowanie i sprawdzanie przeniesienia i bitu zerowego
Pięć odpowiedzi:
stevenvh
2012-03-29 19:14:47 UTC
view on stackexchange narkive permalink

Nie znam mikrokontrolera PIC, więc podam bardziej ogólną odpowiedź. (edytuj: odpowiedź specyficzna dla PIC dodana na dole tego postu)

Szczególnie mniejsze mikrokontrolery, takie jak 8-bitowe i ich pochodne, są ograniczone w tym, co mogą zrobić w pojedyncza instrukcja. Instrukcja może zawierać adres docelowy skoku, ale nie dwa z nich, więc then-else nie działa. Masz tylko część if-then , ale to wystarczy. Istnieją dwa podejścia. Niektóre kontrolery pozwalają na przeskoczenie do podanego adresu, jeśli warunek jest spełniony, inne pozwalają tylko na pominięcie następnej instrukcji. W pierwszym przypadku twój kod będzie wyglądał następująco:

  jeśli test zakończy się sukcesem goto test-successtest-failed pierwsza instrukcja bloku `else` ... goto ciągła test-sukces pierwsza instrukcja` then` block ... kontynuuj pierwszą instrukcję po if-then-else  

Jeśli możesz tylko pominąć następną instrukcję, napiszesz coś takiego jak

  jeśli-test-się powiedzie pomiń następną instrukcję goto test-failedtest-success pierwsza instrukcja bloku `then` ... goto continuetest-failed pierwsza instrukcja bloku` else` ... kontynuuj pierwszą instrukcję po if-then-else  

Sam test również ma ograniczone możliwości. Jakby nie można podać dwóch liczb, aby je porównać. To, co robisz, to ładowanie akumulatora pierwszą liczbą iw następnej instrukcji odejmowanie drugiej liczby. Spowoduje to ustawienie / wyczyszczenie kodów warunków, takich jak zero i flagi przenoszenia. Instrukcje warunkowe będą testować te flagi. Więc jeśli chcesz napisać if A = B then do-equal else do-not-equal to będzie

  załaduj akumulator z A odejmij B od akumulatora, jeśli zero -flag set goto do-equaldo-not-equal pierwsza instrukcja bloku `else` ...
goto continueo-equal pierwsza instrukcja bloku `then` ... kontynuuj pierwszą instrukcję po if-then-else  

Ważne: instrukcja zestawu instrukcji powie ci, na które kody warunków wpłynie dana instrukcja. Na przykład w Z80 instrukcja ld (oznaczająca „load accumulator”) nie zmieni żadnych flag. Więc tutaj ładowanie akumulatora nie jest wystarczające do określenia, czy dane są zerowe.


edytuj
OK, więc poszukałem kilku informacji i znalazłem następujące informacje:
PIC ma tylko 2 warunkowe instrukcje skoku, BTFSS i BTFSC .

BTFSS : Test bitowy F, Pomiń, jeśli ustawiono
Składnia: BTFSS f, b
gdzie f jest rejestrem [0..127]
i b jest bitem w tym rejestrze, który ma być testowany [0..7]
Opis: Jeśli bit w rejestrze to 0 , wykonywana jest następna instrukcja. Jeśli bit ma wartość 1 , następna instrukcja jest odrzucana, a zamiast niej wykonywany jest NOP .

BTFSC : Bit Test F, Pomiń, jeśli wyczyść
Składnia: BTFSC f, b
gdzie f jest rejestrem [0..127]
i b jest bitem w tym rejestrze, który ma być testowany [0..7]
Opis: Jeśli bit w rejestrze to 1 , wykonywana jest następna instrukcja. Jeśli bit ma wartość 0 , następna instrukcja jest odrzucana, a zamiast tego wykonywany jest NOP .

Rok Jarc
2012-03-29 18:23:36 UTC
view on stackexchange narkive permalink

Na razie odpowiem tylko na pierwszą część pytania.

Nie wspominasz o rodzaju X - załóżmy, że jest to znak ze znakiem. Znak ze znakiem ma b.7 == 1 gdy jest ujemne , więc musimy tylko sprawdzić stan tego bitu.

  // sprawdzenie, czy bit 7 w X jest wyczyszczony (X.7 == 0) BTFSC X, 7 // jeśli X.7 == 0 (X jest dodatnie) pominiemy następną instrukcję GOTO BGOTO A // sprawdzanie, czy ustawiony jest bit 7 X (X.7 == 1) BTFSS X, 7 // if X.7 == 1 (X jest ujemne) pominiemy następną instrukcję GOTO AGOTO B  

Oto link do fajnego przewodnika: Przewodnik po typowych konstrukcjach programowania w składaniu PIC

Powyższy przykład znajduje się na stronie 7.

Spróbuj samodzielnie znaleźć pozostałe odpowiedzi. Wskazówka: komentarz Clabacchio jest bardzo przydatny.

Czy to to samo, co: Jason Thweatt. „Przewodnik po typowych konstrukcjach programistycznych PIC”. http://www.ucpic.byethost7.com/Downloads/ApuntesAssembler/Apunte2.pdf?
tak! dzięki za ostrzeżenia, nie zauważyłem, że stary link nie działa. będzie edytować.
Rocketmagnet
2012-03-29 19:27:42 UTC
view on stackexchange narkive permalink

Aby sprawdzić, czy liczba całkowita jest ujemna, wystarczy przetestować górny bit. Jeśli górny bit to 1, to jest ujemny.

Teraz, dla 8-bitowej liczby całkowitej na wspomnianym 8-bitowym clabacchio, możesz użyć odejmowania, aby wykonać test. Jednak z reguły nie jest to optymalne:

  1. PIC mają przydatne instrukcje btfsc i btfss, których można użyć do bezpośredniego przetestowania górnego bitu, jak wspomniano w rokujarc. Może to być użyte nawet do testowania 16- i 32-bitowych liczb całkowitych (a nawet liczb zmiennoprzecinkowych!)

Warto to zauważyć, nawet w C, ponieważ widziałem kompilatory Microchip C produkujące głupi kod. Podczas testowania, czy 16-bitowa liczba całkowita jest większa od zera, dosłownie utworzy zespół, aby odjąć liczbę całkowitą od zera i sprawdzić flagi, zamiast po prostu użyć btfss.

Więc, kiedykolwiek I ' pisząc PIC C, zawsze sprawdzam wyjście zespołu, aby zobaczyć, czy wygląda rozsądnie. A potem zwykle piszą makra do wykonywania operacji. (BTW, tak naprawdę nie sprawdzałem tych makr, są tuż przy mojej głowie).

  #define IF_NEGATIVE_16_BIT (x) if (* ((int8 *) (( &x) +1)) & 0x80) #define IF_NEGATIVE_32_BIT (x) if (* ((int8 *) ((&x) +3)) & 0x80)  
  1. Inne mikrokontrolery mają instrukcję AND. Wystarczy ORAZ najwyższy bajt liczby całkowitej z 0x80. Jeśli ustawiona zostanie flaga zera, liczba całkowita nie była ujemna.
Olin Lathrop
2012-03-29 19:52:33 UTC
view on stackexchange narkive permalink

Aby dokonać porównań liczb całkowitych i większości innych rzeczy w języku asemblerowym, musisz zrozumieć, w jaki sposób reprezentowane są liczby.

Większość zmiennych w małym systemie osadzonym jest bez znaku, a przynajmniej powinna. Programiści języków wysokiego poziomu, przyzwyczajeni do większych systemów, zwykle o tym nie myślą i używają zmiennych ze znakiem, gdy potrzebny jest tylko niepodpisany. Praca bez znaku jest ogólnie łatwiejsza na niskim poziomie.

Twój kod jest przeznaczony dla PIC 16, więc założę, że używasz asemblera MPASM. Mam kilka makr i innych udogodnień, które pomagają w takich rzeczach, jak porównywanie wielkości w moim wspólnym pliku dołączanym STD.INS.ASPIC, który jest częścią mojego środowiska programistycznego PIC. W szczególności makra SKIP_WLE (pomiń, jeśli W było mniejsze lub równe) i SKIP_WGT (pomiń, jeśli W było większe niż) służą do porównań liczb bez znaku.

PIC ma bit statusu przeniesienia, nazywany C, które jest wyjściem przeniesienia jednostki ALU. Ten bit można przetestować po dodaniu lub odjęciu, aby sprawdzić, czy nastąpiło przeniesienie wysokiego bitu ALU. Sposób, w jaki odejmowanie działa z liczbami dopełnienia do dwójki, polega na tym, że bit C staje się bitem niepożyczanym po odjęciu. Aby skomplikować sprawę, instrukcje PIC odejmują rejestr W od operandu, a nie odwrotnie. Musisz wykonać jakąś mentalną gimnastykę, aby śledzić, czy C nie jest pożyczką i co tak naprawdę zostało odjęte od tego, co właściwie oznacza pożyczka. Zrobiłem to wszystko raz i zawarłem wynik w tych dwóch prostych makrach, więc nie muszę o tym myśleć za każdym razem i ryzykować, że coś zepsuje. Na PIC 16, SKIP_WLE zamienia się w pojedynczą instrukcję BTFSS STATUS, C i SKIP_WGT zamienia się w BTFSC STATUS, C.

Oto jak użyłbyś tych makr w kodzie:

 maxok equ 37; maksymalny poziom OK w zbiorniku ... ;; Sprawdź poziom w zbiorniku i uruchom procedurę wyjątku, jeśli tak jest; za wysoko.; banksel tanklev; ustaw bank na dostęp do TANKLEV
movf tanklev, w; uzyskaj pełny poziom zbiornika sublw maxok; porównaj z maksymalnym normalnym poziomem skip_wle; poziom zbiornika mieści się w zakresie? goto ohcrap; no ;; Poziom w zbiorniku mieści się w normalnych granicach roboczych .; 

W STD.INS.ASPIC jest wiele innych przydatnych rzeczy. Mam również preprocesor, który dodaje wiele przydatnych funkcji do języka MPASM. Na przykład może wykonywać obliczenia zmiennoprzecinkowe w czasie budowania, może wykonywać rzeczywiste operacje na łańcuchach w celu budowania nazw symboli, ma bardziej elastyczne możliwości makr i wiele więcej.

davidcary
2012-10-12 20:28:05 UTC
view on stackexchange narkive permalink

16-bitowe porównanie

  • X = XH: XL bajty Hi i Lo zmiennej RAM X,
  • Y = YH: YL bajty Hi i Lo zmienna RAM Y.

Wszystkie wartości są bez znaku.

 ; if (y < x) movfw XL subwf YL, w movfw XH skpc; c = 0 oznacza pożyczkę, którą musimy propagować. incfsz XH, w; obsłuż XH = 0xff poprawnie, w przeciwieństwie do `` incf XH, w ''. subwf YH, w skpnc goto else; następnie:; / * y jest mniejsze niż x * / ... goto endifelse :; / * y NIE jest mniejsze niż x * / ... endif :; if (x < = y) movfw XL subwf YL, w movfw XH skpc; c = 0 oznacza pożyczkę, którą musimy propagować. incfsz XH, w; obsłuż XH = 0xff poprawnie, w przeciwieństwie do `` incf XH, w ''. subwf YH, w skpc goto else; następnie:; / * x jest mniejsze lub równe y * / ... goto endifelse :; / * x NIE jest mniejsze lub równe y * / ... endif :; if (X == Y) movf XH, w xorwf YH, w skpz goto else movf XL, w xorwf YL skpz goto else; następnie:; / * X równa się Y * / ... goto endifelse :; / * X to nie to samo co Y * / ... endif:  

Programiści języka asemblera zazwyczaj zmieniają znaczniki „else:” i „endif:” na unikalną (i miejmy nadzieję opisową) etykietę dla każdej instrukcji if. Może coś w rodzaju „then_in_normal_range:”, „else_outside_normal_range:” i „finish_range_handling:”. (W przeciwieństwie do języków wyższego poziomu, takich jak Pascal i BASIC, w których używamy tych samych słów „then” i „else” i endif "dla każdej instrukcji if.).

Powyższy kod działa tylko wtedy, gdy X i Y znajdują się w pamięci RAM - PIC16f87x wymaga innych instrukcji, aby porównać X ze stałą wartością.

Jednym ze sposobów obsługi 16-bitowych liczb ze znakiem jest najpierw odwrócenie wysokiego bitu

  movlw 0x80xorwf XH, wxorwf YH, w  

, a następnie użycie powyżej kodu porównania. później przywróć oryginalne wartości, ponownie odwracając wysoki bit

  movlw 0x80xorwf XH, wxorwf YH, w  

.

ps Często można uzyskać znacznie szybszą odpowiedź na pytania dotyczące PIC16f87x, przeszukując listę PIC witryna internetowa http://piclist.com/ oraz wiki Microchip http://microchip.wikidot.com. Aby porównać języki asemblera, zobacz stronę „Assembly Language Comparisons” na stronie Microchip wiki i Metody matematyczne porównania mikrokontrolerów PIC na stronie PIClist (z której powyższy fragment jest małym fragmentem).



To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...