Assembler podstawowe operacje - kilka pytań

0

Pytanie 1. ustawianie bitów - rozumiem ze robi się to przez ustawienie maski + operacja logiczna. Rozumiem że może być taka sytuacja, że wynik który chce otrzymać nie uda mi się zrobić jedną maską i operacją logiczną tylko będę musiał np. zrobić 2x maskę + operacja logiczna ?

Przykład z wikipedi: zerowanie dwóch najmłodszych bitów

operacja AND

Słowo: 10010111
Maska: 11111100
Wynik: 10010100

Pytanie 2. co do maski czy to ma jakieś znaczenie czy zamiast tej maski dam np. taką: 10011100. Wynik będzie ten sam.

Pytanie 3.

Mam takie 2 instrukcje czym one się różnią:

ORR R1, #(1<<28)(1<<26)
MOV R2,#((1<<13) (1<<14)) // maska -> ustawienie jedynek na 13 i 14 pozycji ?

Pytanie 4. Po co się robi takie operacje, to STR na końcu ?

LDR R0, =RCC_AHB1ENR
LDR R1, [R0] //odczyt
ORR R1, #1<<6 //przesuniete o 6 miejsc zgodnie z kierunkiem strzalek //mod
STR R1, [R0] //zapis

Pytanie 5.

Instrukcja STR

Powiedzmy, że mam:

LDR R1,[R0]
STR R1,[R0]

Wiem, że STR zapisuje wartość rejestru w pamięci w przeciwieństwie do LDR który to ładuje wartość rejestru z pamięci.

Tylko, że ja nie rozumiem czym to się różni.

Pytanie 6.

Instrukcja TST

TST R1,#1

W jakim przypadku ustawiana jest flaga?

Jeżli do rejestru R1 wrzucę 0x01 to się nie ustawia. a już dla R1 = 0x02 tak. Czyli żeby ustawiła się flaga wynikiem muszą być same zera ?

TST to operacja AND czyli
dla R1 = 0x01 mam 01 & 01 = 01
dla R1 = 0x02 mam 10 & 01 = 00

Dla takiego kodu


            1. CMP                R5,#255 ;
            2. ITE                  EQ ;
            3. MOVEQ           R1,#1<<13
            4. MOVNE           R1,#1<<29 ;reset jest na 29
            5. STR                R1,[R0]

  1. Porównuje wartość w rejestrze R5 z 255. Jeżeli jest taka sama ustawia się flaga Z = 1
  2. Jeżeli Z == 1 to wykona sie linijka 3, jeżeli nie to wykona się linijka 4.

Pytanie 7. Po co piszę MOVEQ / MOVNE ?? Równie dobrze mogę wywalić linijkę nr 2 ( ITE ) i też będzie chyba działać, lub zostawić ITE i zmienić MOVEQ -> MOV i MOVNE -> MOV

Z góry dzięki za pomoc

0

@Shalom @msm @Azarien pomożecie :) ?

0
  1. To chyba tylko jak nie umiesz logiki :D Każdą zmianę można wykonać za pomocą jednej maski.
  2. Bez różnicy
  3. Nie wiem co to za asembler ale zgaduje że to STR to jakieś store register value i zapisuje wartość z R1 do miejsca w pamięci pod adresem zapisanym w R0. Po co? Ano żeby wartość zapisać w pamięci. Poza trywialnymi programami trudno wszystkie dane trzymać w rejestrach, bo rejestrów masz tylko kilka i mieszczą niewiele danych. A jeśli piszesz program który wczytuje Pana Tadeusza i zamienia wszystkie literki na duże? Gdzie chcesz tego Pana Tadeusza przechować? ;]
  4. Jak to nie rozumiesz czym się różni? o_O Jedno wczytuje wartość a drugie ją zapisuje. Wyobraź sobie że zapisujesz na dysku plik tekstowy o treści "ala ma kota", to jest odpowiednik STR. Rozumiesz chyba że otwarcie pliku i wypisanie jego zawartości na ekran (odpowiednik LDR) to jest zupełnie co innego?
  5. Tak trudno sprawdzić w dokumentacji http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/CIHCDEHH.html ? To po prostu ustawia jako flagę wynikową rejestr and operand.
  6. Wydaje mi się że masz racje, niepotrzebnie są tutaj dwa warunkowe mechanizmy na raz. Wystarczyłoby samo ITE + mov + mov, albo same moveq+movne
0
Shalom napisał(a):
  1. To chyba tylko jak nie umiesz logiki :D Każdą zmianę można wykonać za pomocą jednej maski.
  2. Bez różnicy
  3. Nie wiem co to za asembler ale zgaduje że to STR to jakieś store register value i zapisuje wartość z R1 do miejsca w pamięci pod adresem zapisanym w R0. Po co? Ano żeby wartość zapisać w pamięci. Poza trywialnymi programami trudno wszystkie dane trzymać w rejestrach, bo rejestrów masz tylko kilka i mieszczą niewiele danych. A jeśli piszesz program który wczytuje Pana Tadeusza i zamienia wszystkie literki na duże? Gdzie chcesz tego Pana Tadeusza przechować? ;]
  4. Jak to nie rozumiesz czym się różni? o_O Jedno wczytuje wartość a drugie ją zapisuje. Wyobraź sobie że zapisujesz na dysku plik tekstowy o treści "ala ma kota", to jest odpowiednik STR. Rozumiesz chyba że otwarcie pliku i wypisanie jego zawartości na ekran (odpowiednik LDR) to jest zupełnie co innego?
  5. Tak trudno sprawdzić w dokumentacji http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/CIHCDEHH.html ? To po prostu ustawia jako flagę wynikową rejestr and operand.
  6. Wydaje mi się że masz racje, niepotrzebnie są tutaj dwa warunkowe mechanizmy na raz. Wystarczyłoby samo ITE + mov + mov, albo same moveq+movne

Ad. 5 Dla mnie najdziwniejsze jest to że zapisuje to do R0 a przecież jak potem używam tego rejestru np dla LDR R0, [R6] to chyba nadpisuje to co zapisałem w R0, jaki to ma sens?

Mam jeszcze pytanie Czym różnią się od siebie operacje:

LDR R0, [R1]
i
MOV R0, [R1]

0

No bo tak jak pisałem rejestrów jest mało ale CPU potrafi operować tylko na nich. Nie da się np. dodać dwóch wartości z pamięci. Musisz je pobrać najpierw do rejestrów CPU. Stąd też non stop co innego musisz ładować do rejestrów. Ładujesz, wykonujesz obliczenia, zapisujesz wyniki i ładujesz coś innego. Nie traktuj rejestrów jako "zmiennych", bo to jest zupełnie inna koncepcja.

Jeśli chodzi o mov i ldr to jest to trochę bardziej złożona kwestia i wynika z tego że ARM ma instrukcje stałej długości (w opzeciwieństwie do jakiegoś x86 na przykład). To znaczy że każda instrukcja MUSI się zmieścić na z góry ograniczonej liczbie bajtów -> konkretnie na 4 bajtach. Nie trudno zauważyć że trudno byłoby w takim układzie zrobić mov do jakiegoś rejestru z wartością która miałaby 4 bajty, bo już samo mov i rejestr zabierają trochę z tych 4 bajtów na instrukcje, a gdzie jeszcze upakować tą wartość? Stąd też masz ldr które powoduje że kompilator wartość wrzuca do pamięci i w tej instrukcji ładuje z pamięci tą wartość do rejestru.

0
Shalom napisał(a):
  1. Bez różnicy

Bez różnicy dla tego konkretnego przypadku. Jeśli chcesz wyzerować 2 najmłodsze bity na "przypadku ogólnym" to tak, jak mówi Wiki: 11111100.

0

A operacje odczyt modyfikacja zapis np. coś takiego


                                1. LDR 	        R0,=GPIOG_MODER				;tryb pracy lini 13 i 14 portu G - wyjscie
				2. LDR		R1,[R0]
				3. ORR		R1,R1,#((1<<(2*13)) :OR: (1<<(2*14)))
				4. STR		R1,[R0]

rozumiem że to podstawowe operacje. Proszę o zweryfkowanie czy dobrze to rozumiem.

  1. Ładuje zawartość rejestru GPIOG_MODER do rejestru R0, rejestr GPIOG_MODER pozwala ustawić poszczególne bity w rejestrze jako wejścia albo wyjścia.

  2. W linijce 3 ustawiam te bity w rejestrze, czyli ustawiam bit 26 i bit 28 na 1 chyba. Tylko to szczerze mówiąc nie rozumiem jak działa ta cała linijka. Nie rozumiem tego zapisu.

No i potem mam to STR i do rejestru R1 czyli do rejestru gdzie mam poustawiane odpowiedno te bity w rejestrze zapisuje rejesre R0 w którym miałem niepoustawiane te bity. O co tu chodzi.. czy przez to nie nadpisuje tego co zrobiłem chwilę wcześniej ?

@Shalom bardzo Cie proszę o wyjaśnienie tego kodu.

Na zajeciach programowalismy tez ARM w C i rozumiem ze powyzszy zapis jest równoznaczny temu w C :

GPIOG->MODER |= (1<<(2*13)) | (1<<(2*14));  // linie G13 i G14 jako wyjscia
0

o_O mam wrażenie że niestety ale programowanie to nie jest działka dla ciebie, bo brakuje ci czytania ze zrozumieniem i jakiegokolwiek rozumienia logiki...

  1. 2*13 = 26, a << to przesuniecie bitowe w lewo, czyli dodawanie zer z prawej strony liczby binarnej. Tzn 1<<3 daje nam 1000, czyli liczbę z zapalonym 4 bitem.
  2. STR to jest store register to memory o czym juz wyżej pisałem. To NIE JEST operacja na rejestrach! W twoim przypadku masz STR R1,[R0] czyli zapisanie wartości rejestru R1 do PAMIĘCI pod adresem wskazanym przez R0.

Co więcej ja na ARM znam się bardzo słabo, ale potrafie otworzyć http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/BABDJCHA.html i sie upewnić...

1 użytkowników online, w tym zalogowanych: 0, gości: 1