Obraz zawierający tekst, Czcionka, Grafika

Opis wygenerowany automatycznie 

Kierunek Informatyka

 

Instrukcja do ćwiczeń laboratoryjnych nr:

3

Nazwa przedmiotu:
Programowanie niskopoziomowe

Temat: Rozkazy arytmetyczno – logiczne, przesunięcia bitowe, deklaracja zmiennych

Tryb studiów: stacjonarny
i niestacjonarny

Czas trwanie ćw.

2x45 min

Autor materiałów: dr Marcin Skuba

 

I. Treści programowe

Rejestry procesora, pamięć, wysyłanie i wysyłanych danych na stos oraz pobieranie, działania matematyczne - rozkazy arytmetyczne i logiczne, przesunięcia bitów.


II. Cel ćwiczenia

Opanowanie umiejętności używania rozkazów dodawania, odejmowania, inkrementacji dekrementacji, mnożenia i dzielenia oraz OR, AND, XOR i NOT. Zrozumienie operacji przesuwania bitów w prawo i w lewo oraz deklaracji zmiennych w pamięci operacyjnej.

 

III. Materiały dydaktyczne:

Wybrane instrukcje arytmetyczne, logiczne, bitowe

Składnia rozkazu

Opis

Przykład

INC rejestr/pamięć

Zwiększa o jeden wartość operandu.

INC AX  
AX = AX + 1

DEC rejestr/pamięć

Zmniejsza o jeden wartość operandu.

DEC AX  
AX = AX - 1

ADD rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Dodaje wartość operandu drugiego do pierwszego i wynik zapisuje w operandzie pierwszym.

ADD AX, BX  ;AX = AX + BX
ADD AX, 7  ;
AX = AX + 7

SUB rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Odejmuje wartość operandu drugiego od pierwszego i wynik zapisuje w operandzie pierwszym.

SUB AX, BX ;AX = AX - BX
SUB AX, 7   ;
AX = AX – 7

MUL rejestr/pamięć

Mnożymy (wartości dodatnie) rejestr akumulatora (AX/EAX/RAX) z podanym operandem. Wynik zapisuje do rejestru akumulatora lub pary DX:AX, EDX:EAX, RDX:RAX.

MUL BX      ;DX:AX = AX * BX

MUL CL       ; AX = AL*CL            
MUL zm1   ;
AX = AX *zm1

MUL CL       ;AX = AL*CL  (1 bajt)
MUL BX      ;DX:AX = AX*BX   ;(2 bajty)

iMUL rejestr/pamięć

Mnożenie wartości ze znakiem (wartości ujemnych).

MOV bx, -2

MOV ax, 3

iMUL bx   ; FFFA  - 1111 1010

NOT ax     ;5         - 0000 0101

INC ax       ;wartość bezwzględna =6

DIV rejestr/pamięć

Dzieli wartość (bez znaku) w rejestrze AX lub parze rejestrów DX:AX, EDX:EAX, RDX:RAX przez podany operand. Wynik zachowuje w rejestrze AX lub parze DX:AX, EDX:EAX, RDX:RAX. Rejestr akumulatora zawiera wynik, natomiast rejestr danych (DX, EDX, RDX) zawiera resztę z dzielenia.

DIV BX ;
AX = AX / BX (DX zawiera resztę z dzielenia)
DIV zmienna1 ;
 
AX = AX / zmienna1 (DX zawiera resztę z dzielenia)

iDIV rejestr/pamięć

Dzielenie ze znakiem

 

AND rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Wykonuje koniunkcję logiczną na bitach podanych operandów Wynik umieszcza w operandzie pierwszym. Jeśli dany bit obu operandów jest równy jeden to bit w wyniku będzie miał wartość jeden. W przeciwnym wypadku dany bit wyniku będzie miał wartość zero.

AND AX, 1 ;
AX = 0000000000000001 (binarnie) = 1 (dziesiętnie)
AND AX, 11111111 ;
AX = 0000000011111111 (binarnie) = 255 (dziesiętnie)

OR rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Wykonuje alternatywę logiczną na bitach podanych operandów. Wynik umieszcza w operandzie pierwszym. Jeśli dany bit jednego z operandów jest równy jeden to bit w wyniku będzie miał wartość jeden. Bit wyniku będzie miał wartość zero tylko wtedy, gdy dane bity operandów będą równe zero.

OR AX, 0FFh ;
AX = 1111111111111111 (binarnie) =
255/-1 (dziesiętnie)

XOR rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Wykonuje alternatywę wykluczającą na bitach podanych operandów. Wynik umieszcza w operandzie pierwszym. Jeśli dane bity operandów mają taką samą wartość (jeden/jeden lub zero/zero) to bit w wyniku ma wartość zero. Jeśli dane bity mają różne wartości (jeden/zero, zero/jeden) to bit w wyniku ma wartość jeden.

XOR AX, AX ;
 
AX = 0

SAL/SHL rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Przesuwa w lewo bity operandu pierwszego o podaną ilość bitów w operandzie drugim. Starszy przesunięty bit, zostaje zachowany w fladze CF (Carry Flag), a młodsze bity są wypełniane zerami.

 

SAL — schemat

SAR/SHR rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Instrukcja SAR przesuwa w prawo bity operandu pierwszego o podaną ilość bitów w operandzie drugim. Najmłodszy przesunięty bit, zostaje wpisany do flagi CF, a najstarszy bit zostaje zachowany. Instrukcja SHR działa podobnie, różni się tylko tym, że zeruje najstarszy bit (nazywany również bitem znaku).


SAR — schemat


SHR — schemat

ROL/RCL rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Instrukcja ROL przesuwa logicznie w lewo operand pierwszy o ilość bitów podaną w operandzie drugim. Nie używa flagi CF, więc najmłodszy bit przyjmuje wartość najstarszego bitu. Instrukcja RCL robi tę samą czynność, ale przy użyciu flagi CF, gdzie najmłodszy bit przyjmuje wartość, która była w CF, a znacznik CF przyjmuje wartość najstarszego bitu.


ROL — schemat


RCL — schemat

 

ROR/RCR rejestr/pamięć, rejestr/pamięć/wartość natychmiastowa

Instrukcja ROR przesuwa logicznie w prawo operand pierwszy o ilość bitów podaną w operandzie drugim. Nie używa flagi CF, więc najstarszy bit przyjmuje wartość najmłodszego bitu. Instrukcja RCR robi tę samą czynność, ale przy użyciu flagi CF, gdzie najstarszy bit przyjmuje wartość, która była w CF, a znacznik CF przyjmuje wartość najmłodszego bitu.
ROR
— schemat


RCR — schemat

 

Wybrane znaczniki stanu i znaczniki sterujące w rejestrze EFLAGS:
 SF – znacznik znaku
 OF – znacznik przepełnienia
 CF – znacznik przeniesienia
 PF – znacznik parzystości
 ZF – znacznik zera

  0 AND 0 = 0     0 OR 0 = 0      0 XOR 0 = 0   NOT 0 = 1
  0 AND 1 = 0     0 OR 1 = 1      0 XOR 1 = 1   NOT 1 = 0
  1 AND 0 = 0     1 OR 0 = 1      1 XOR 0 = 1
  1 AND 1 = 1     1 OR 1 = 1      1 XOR 1 = 0


  and ax, 1         -  wyzeruje wszystkie bity z  wyjątkiem bitu numer 0.
  or bx, 1111b  -  ustawia (włącza) 4 dolne bity. Reszta bez zmian.
  xor cx, cx        -  CX = 0 – zerowanie wartości rejestru
  not dh             -  DH jest 0 tam, gdzie było 1

 

Deklaracja zmiennych (Na niebiesko zapisano nazwy zmiennych, na zielono zarezerwowany rozmiar danych)

   
dane0 db ?                     ;bajt bez nadanej wartości początkowej
    dane1 db 7                      ;bajt (8 bitów) z nadaną wartością 7

    dane2 db 1, 2, 3, 4        ;ciąg czterech bajtów o nadanych wartościach

    dane3 db "a"                  ;bajt przechowujący znak "a"

    dane4 dw 5                     ;słowo (2 bajty, 16 bitów) z nadaną wartością 5

    dane5 dd 0                     ;podwójne słowo (4 bajty, 32 bity)

    dane6 dq 0                      ;poczwórne słowo (8 bajtów, 64 bity)

    dane7 dt 0                      ;dziesięć bajtów

    dane8 db "PWSZ Krosno $"    ;ciąg bajtów (znaków) - napis

    dane9 db 128 dup(0)               ;ciąg 128 bajtów z wartością zero

    dane10 db 64 dup("a")            ;ciąg 64 bajtów z wartością znak "a"

 

Przykład zapisu daty w jednym rejestrze dwubajtowym:

  wartość od 0-99   (Rok - Y)                   ->
YYYYYYY (potrzebne maksymalnie 7 bitów)
  wartości 1-12        (Miesiąc – M)          -> MMMM   (potrzebne maksymalnie 4 bity)
  wartość 1-31         (Dzień – D)               ->
DDDDD    (potrzebne maksymalnie 5 bitów)
 
YYYYYYY MMMM DDDDD

Przykład: 15 Maj 2026 roku
0011010   0101    01111
   26 (1Ah)        05(5h)       15 (0FCh)   

      ROK            Miesiąc       Dzień
           

mov   ax, 26            ; 00000000 00011010      ; 1A
      mov   bx, 05            ; 00000000 00000101      ; 05
      mov   cx,
15            ; 00000000 00001111      ; F
     

      xor     dx, dx            ; 00000000 00000000      ; 0
      mov   dx,
ax            ; 00000000 00011010      ; 1A
      shl      dx, 4              ; 00000001 10100000      ; 1A0
      xor     dx, bx            ; 0000000
1 10100101      ; 1A5
      shl      dx,
5              ; 00110100 10100000      ; 34A0
      xor     dx,
cx            ; 00110100 10101111      ; 34AF

 

Wartości ujemne

 

Zapisywanie liczb ujemnych w asemblerze opiera się na sprytnym triku matematycznym zwanym kodem uzupełnień do dwóch (U2). Pozwala on procesorowi traktować odejmowanie tak samo jak dodawanie.

Przykład  8-bitowy (jeden bajt). Załóżmy, że chcemy zapisać liczbę -5.

 

Metoda "Odwróć i dodaj jeden"

To najprostszy przepis na zamianę liczby dodatniej na ujemną w systemie binarnym:

  1. Zapisz liczbę dodatnią binarnie:

 

      5 to 0000 0101

 

  1. Odwróć wszystkie bity (NOT):

Zamień zera na jedynki, a jedynki na zera.

 

1111 1010 (to się nazywa uzupełnienie do jedynki)

 

  1. Dodaj 1 do wyniku:

1111 1010 + 1 = 1111 1011

 

Wynik 1111 1011 (czyli FBh w hex) to w asemblerze liczba -5.

 

 

Najłatwiej zrozumieć to na przykładzie licznika w samochodzie. Jeśli masz stan 000 i cofniesz go o 1, zobaczysz 999.

W komputerze działa to identycznie:

 

Kluczowa cecha: Najstarszy bit

W asemblerze (i całej architekturze x86/x64) najstarszy bit (ten najbardziej z lewej) pełni rolę "strażnika znaku":

Dlatego dla 8 bitów:

 

 

IV. Zadania


Zadanie 1.
Napisz program, który pobiera znak z klawiatury oraz wyświetla na ekran znak następny w kolejności. Np. po wciśnięciu znaku ‘a’ program wyświetla ‘b’, itd. 

Zadanie 2.

Napisz program, który pobiera z klawiatury małe litery i wyświetla na ekranie te same litery jako duże. 

Zadanie 3.
Przepisz przykłady z tabeli powyżej sprawdzając działanie rozkazów arytmetyczno logicznych sprawdzając zawartość rejestrów w TD.

Użyj również wartości ujemnych i spróbuj odczytać wynik (przekonwertuj do wartości bezwzględnej).

Zadanie 4.

Wzorując się na przykładzie powyżej zapisz w jednym rejestrze DX swoją datę urodzenia według kolejności: MMMMDDDDDRRRRRRR.

Zadanie 5.

Napisz program odczytujący kolejne wartości: rok, dzień, miesiąc z rejestru DX z poprzedniego zadania. Wartości zapisz w zmiennych w pamięci operacyjnej o nazwie rok, dzien, miesiac.