Transcript MOV

Architektura systemów komputerowych
jesień 2014
Wykład 7
Mikroprocesor Intel 8086
oraz koprocesor matematyczny
8087
dr inż. Wojciech Bieniecki
Instytut Nauk Ekonomicznych
i Informatyki
http://wbieniec.kis.p.lodz.pl/pwsz
Geneza procesora
8086 jest 16-bitowym mikroprocesorem wprowadzonym na rynek
w 1978 roku.
Mikroprocesor został zaprojektowany przez firmę Intel jako
następca 8-bitowego 8080/8085.
Jego zastosowanie (w szczególności jego odmiany z 8-bitowym
interfejsem - 8088) w pierwszych ogólnodostępnych komputerach
osobistych (IBM PC), doprowadziło do jego wielkiej popularyzacji i
dalszego rozwoju.
2
Parametry procesora
architektura CISC;
przestrzeń adresowa pamięci - 1MB w trybie rzeczywistym;
16-bitowa magistrala danych;
20-bitowa magistrala adresowa;
częstotliwość sygnału zegarowego do 10MHz;
91 podstawowych typów rozkazów;
przestrzeń adresowa urządzeń wejścia/wyjścia - 64kB;
możliwość wykonywania operacji bitowych, bajtowych, o długości słowa i łańcuchowych;
7 trybów adresowania argumentów w pamięci;
dwa tryby pracy – minimalny i maksymalny;
16-bitowa jednostka arytmetyczno logiczna (ALU);
16-bitowe rejestry ogólnego przeznaczenia;
6-bajtowa kolejka rozkazów.
3
Nowe rozwiązania względem
procesorów 8-bitowych
Rozszerzenie możliwości adresowanie operandów
W mikroprocesorach 8-bitowych stosowano 4 tryby adresowania:
rejestrowy, natychmiastowy, pośredni i bezpośredni.
W mikroprocesorze 8086 dodano nowe rejestry pozwalające wprowadzić
tryby adresowania: indeksowy, bazowy i indeksowo-bazowy
Segmentacja obszaru pamięci
Mechanizm wprowadzono dla rozdzielenia obszarów przeznaczonych dla
programu, danych i stosu.
Mikroprocesor zawiera cztery rejestry segmentowe, w których
przechowywane są adresy początków segmentów.
Taki sposób adresowania ułatwia relokację programów i danych oraz
umożliwia łatwe stworzenie prostego mechanizmu ochrony pamięci.
4
Nowe rozwiązania względem
procesorów 8-bitowych
Mechanizmy przyspieszenia pracy
Dwie jednostki procesora: wykonawcza (dekodowanie i wykonanie operacji) i
interfejsowa (współpraca z pamięcią)
Dzięki takiej architekturze 8086 jest w stanie w jednocześnie wykonywać operację
jednego rozkazu oraz pobierać kod operacji następnego (przetwarzanie potokowe).
Mechanizmy dla pracy wieloprocesorowej
Dwa tryby pracy. W trybie minimalnym steruje on całym systemem
mikrokomputerowym pełniąc rolę kontrolera magistrali.
Zwykle system taki składa się z jednego obwodu drukowanego i kilku urządzeń
peryferyjnych.
W trybie maksymalnym magistrala jest współdzielona pomiędzy mikroprocesor a
procesory wspomagające.
Funkcje sterownika magistrali przejmuje wtedy osobny element systemu
mikrokomputerowego zwany kontrolerem magistrali.
Tryb ten stosowany jest w przypadku systemów wieloprocesorowych (np. system w
którego skład wchodzi mikroprocesor wraz z koprocesorem matematycznym)
5
Budowa procesora
1. Blok rejestrów ogólnego przeznaczenia
2. ALU z rejestrem flag
3. Blok rejestrów segmentowych wraz z
licznikiem rozkazów.
Jednostka interfejsowa
Bus Interface Unit
4. Generator 20- bit. adresu fiz.
5. Kolejka rozkazów
4
6. Kontroler interfejsu
6
7. Układ kontrolny
3
5
Jednostka wykonawcza
(Execution Unit)
7
1
2
6
Jednostka wykonawcza
ALU dołączona jest do magistrali wewnętrznej mikroprocesora.
Z magistrali tej pobierane są argumenty operacji, a także wysyłany jest na nią wynik
operacji.
Układ wykonawczy nie ma bezpośredniego połączenia z magistralą zewnętrzną
W jej skład wchodzi :
16-bitowa jednostka arytmetyczno-logiczna ALU
Układ sterowania wraz z rejestrem rozkazów
Cztery 16 bitowe rejestry ogólnego przeznaczenia (możliwe korzystanie z rejestrów
8-bitowych)
Czery 16-bitowe rejestry adresowe
16 bitowy rejestr flag
7
Rejestr znaczników (flag)
Flagi zostały podzielone na dwie grupy, tj. kontrolną i arytmetyczną.
Flagi arytmetyczne dostarczają dodatkowych informacji na temat wyniku
ostatniej operacji wykonanej przez jednostkę arytmetyczno-logiczną.
Flagi kontrolne wpływają na sposób pracy mikroprocesora.
8
Rejestr flag
SF (sign flag) - znacznik znaku - równy najbardziej znaczącemu bitowi wyniku
0 - wynik operacji dodatni
1 - wynik operacji ujemny
ZF (zero flag) - znacznik zera
0 - wynik operacji różny od zera
1 - wynik operacji równy zeru
PF (parity flag) - znacznik parzystości - ustawiany w zależności od liczby jedynek w
najmniej znaczących 8 bitach wyniku
0 liczba jedynek w wyniku operacji nieparzysta
1 liczba jedynek w wyniku operacji parzysta
AF (auxiliary carry flag) - znacznik przeniesienia połówkowego (pomocniczego)
0 - brak przeniesienia pomiędzy trzecim i czwartym bitem bajta (BCD)
1 - występuje przeniesienie
CF (carry flag) - znacznik przeniesienia
0 - wynik operacji arytmetycznej nie powoduje powstania przeniesienia z najbardziej
znaczącego bitu
1 - wynik takie przeniesienie powoduje
9
Rejestr flag
OF (overflow flag) - znacznik nadmiaru
0 - suma modulo 2 przeniesień z najbardziej znaczącej pozycji i pozycji przedostatniej
jest równa 0
1 - suma modulo 2 przeniesień z najbardziej znaczącej pozycji i pozycji przedostatniej
jest równa 1 (przekroczenie zakresu w kodzie U2)
IF (interrupt flag) - znacznik przerwań
0 - brak zezwolenia na przyjmowanie przerwań z wejścia INT
1 - zezwolenie na przyjmowanie przerwań
DF (direction flag) - znacznik kierunku, wskazuje, czy zawartości rejestrów SI i DI mają
być zwiększane lub zmniejszane o jeden w czasie wykonywania operacji łańcuchowych
0 - rejestry są zwiększane
1 - rejestry są zmniejszane
TF (trap flag) - znacznik pułapki umożliwiającej pracę krokową
0 - praca krokowa wyłączona
1 - praca krokowa włączona, mikroprocesor po wykonaniu każdego rozkazu wykona skok
do odpowiedniego podprogramu obsługi przerwania
10
Rejestry arytmetyczne
Są to cztery 16-bitowe rejestry ogólnego przeznaczenia
Każdy z tych rejestrów może również działać jako dwa
niezależne rejestry 8-bitowe
Niektóre z instrukcji mikroprocesora używają rejestrów
arytmetycznych do ściśle określonych celów
AX – Akumulator współpracuje z ALU. Niektóre operacje,
których argumenty znajdują się w akumulatorze, wykonywane
są szybciej niż ich odpowiedniki wykorzystujące inne rejestry.
Takie rozkazy jak: mnożenie, dzielenie i operacje
wejścia/wyjścia wymagają użycia akumulatora do
przechowywania argumentu bądź też zapisu wyniku.
BX – Baza Rejestr ten może być używany do adresowania argumentu, znajdującego się w pamięci,
stanowiąc bazę do obliczania adresu.
CX – Licznik (Counter) jest używany w operacjach łańcuchowych oraz pętlach. Po każdej iteracji jego
zawartość jest automatycznie dekrementowana. W rozkazach przesunięć rejestr CL wykorzystywany
jest jako licznik bitów.
DX – Dane wykorzystywany w niektórych operacjach arytmetycznych do przechowywania części
argumentu lub wyniku operacji (mnożenie i dzielenie 16- bitowe). Zawiera on także adres urządzenia
w
11
operacjach wejścia/wyjścia.
Rejestry wskaźnikowe i indeksowe
Ich głównym zadaniem jest wskazywanie miejsca w pamięci, w
którym znajdują się argumenty rozkazu.
Wykorzystywane są w adresowaniu indeksowym, bazowym oraz
indeksowo-bazowym.
Można ich również używać do przechowywania argumentu bądź
wyniku operacji.
SP – wskaźnik stosu (Stack Pointer) Wskazuje adres ostatnio
zapisanego słowa na stosie. Jego zawartość jest automatycznie
inkrementowana lub dekrementowana w zależności od
wykonywanej operacji (POP, PUSH).
BP – wskaźnik bazy (Base Pointer) Pełni on funkcję wskaźnika ogólnego przeznaczenia.
Wykorzystywany jest do adresowania bazowego danych w segmencie stosu.
SI – rejestr indeksowy źródła (Source Index) Uniwersalny rejestr indeksowy.
Jest wykorzystywany w czasie dwuargumentowych operacji łańcuchowych do przetrzymywania adresu
źródła danych. Po każdej kolejnej iteracji jego zawartość jest inkrementowana lub dekrementowana,
zależnie od ustawienia flagi kierunku.
DI – rejestr indeksowy przeznaczenia (Destination Index) Uniwersalny rejestr indeksowy.
Jest wykorzystywany w czasie dwuargumentowych operacji łańcuchowych do przetrzymywania adresu
przeznaczenia danych.Po każdej kolejnej iteracji jego zawartość jest inkrementowana lub
12
dekrementowana, zależnie od ustawienia flagi kierunku.
Rejestry segmentowe
Są to 16-bitowe rejestry, dostępne dla programisty, których zawartość służy
do obliczania adresu fizycznego komórki pamięci.
Rejestry te zawierają adres początkowy danego segmentu pamięci.
Mikroprocesor w zależności od rodzaju segmentu pamięci, do którego chce
się odwołać, wykorzystuje odpowiedni z rejestrów.
Programista ma możliwość zmiany automatycznie wykorzystywanego
rejestru poprzez umieszczenie odpowiedniego prefiksu przed rozkazem, dla
którego zmiana ma zostać zastosowana.
CS – rejestr segmentowy programu (Code Segment register): początek aktualnie używanego segmentu
programu. Wartość ta wykorzystywana jest do obliczania adresu fizycznego kolejnego rozkazu
do pobrania z pamięci.
DS – rejestr segmentowy danych (Data Segment register): początek aktualnie używanego segmentu
danych. Wartość ta wykorzystywana jest do obliczania adresu fizycznego argumentu lub wyniku
aktualnie wykonywanego rozkazu. Wyjątek stanowią rozkazy łańcuchowe, w których zawartość tego
rejestru służy jedynie do obliczania adresu źródła danych.
SS – rejestr segmentowy stosu (Stack Segment register): początek aktualnie używanego segmentu
stosu. Wartość ta wykorzystywana jest do obliczania adresu fizycznego komórki pamięci, na którą
wskazuje wskaźnik stosu (rejestr SP).
ES – rejestr segmentowy dodatkowy (Extra Segment register): początek aktualnie używanego
dodatkowego segmentu danych. Wartość ta wykorzystywana jest do obliczania adresu fizycznego
przeznaczenia dla operacji łańcuchowych (np. rozkazu przenoszenia bloku danych).
13
Rejestry procesora 80386
14
Rodzaje rozkazów wykonywanych
przez procesor
przesłania typu rejestr-rejestr, stos-rejestr, rejestr-stos, rejestr-we/wy, we/wyrejestr
operacje arytmetyczne: dodawanie, odejmowanie, porównanie, mnożenie i
dzielenie dwójkowych liczb całkowitych bez znaku (w kodzie NB) lub ze
znakiem (w kodzie U2), jak również liczb dziesiętnych (w kodzie BCD)
operacje logiczne AND, OR, XOR i NOT, oraz różne rodzaje przesunięć
logicznych
operacje tekstowe (gdy słowa traktowane są jak łańcuchy znakowe):
przepisywanie ciągu słów z jednego obszaru do drugiego, wyszukiwanie i
porównywanie słów
różne rodzaje skoków
sterowanie stanem mikroprocesora
15
Pamięć danych, programu, stos
Pamięć danych i programu jest 8-bitowa; możliwe jest
adresowanie słów wielobajtowych. Stos jest 16-bitowy.
Trzy rodzaje pamięci są adresowane za pomocą wspólnej
magistrali adresowej.
Stos jest to obszar pamięci, do którego wpisujemy dane, bądź są
ładowane adresy w wyniku wykorzystania podprogramów lub
przerwań.
Ze stosu można pobrać najpierw ostatnio wpisaną daną, czyli
odwrotnie do kolejności wpisywania.
16
Organizacja pamięci i tworzenie adresu
fizycznego
20-bitowa magistrala adresową. (adresowanie do
1MB pamięci operacyjnej)
Przestrzeń adresowa podzielona na segmenty o
długości 64kB, rozpoczynające się co 16 bajtów
(kolejne segmenty pamięci mogą nakładać się na
siebie).
Adres fizyczny obliczany jest na podstawie dwóch
16-bitowych składników adresu segmentu oraz
adresu efektywnego (przesunięcia).
Taki sposób adresowania nazywa się
adresowaniem segmentowym.
Do otrzymania adresu fizycznego
stosuje się tzw. generator adresu
fizycznego, znajdujący się w
jednostce interfejsowej. Adres segmentu mnożony jest przez
16, co powoduje że zostaje on przesunięty o 4 bity w lewo
(zwolnione z prawej strony bity przyjmują wartość 0), a
następnie dodaje się do niego adres efektywny obliczony z
zastosowaniem wszystkich modyfikatorów (w przypadku danych)
lub zawartość licznika rozkazów (w przypadku rozkazów).
17
Generowanie adresu fizycznego
Adres logiczny: 0010h:000Fh
(adres początku segmentu:wartość przesunięcia (tzw. adres efektywny))
0010h * 0010h (16 dziesiętne) = 00100h
(dwudziestobitowy adres początku segmentu)
00100h + 000Fh = 0010Fh (adres fizyczny komórki pamięci)
Niejednoznaczność adresowania segmentowego
Adresowanie segmentowe jest niejednoznaczne (jest to spowodowane nachodzeniem na
siebie segmentów), jedna komórka pamięci może mieć kilka adresów logicznych.
Zależnie od wyboru segmentu, względem początku którego komórka pamięci będzie
adresowana, jej adres logiczny będzie inny. W celu rozwiązania tego problemu stosuje się
normalizację adresu logicznego.
18
Ogólna postać rozkazów
asemblera 8086
pole_etykiety pole_operacji pole_argumentów pole_komentarza
START:
MOV
AX, DATA
;wielkość liter nie ma znaczenia
; początek prog.
19
Rozkazy przesłania danych
MOV reg,reg
;np. MOV AX,BX
MOV mem,reg
;np. MOV [1234],AL
MOV reg,mem
MOV reg,stala ;np. MOV AH,#12h
MOV reg,seg
;np. MOV AX,DS
MOV mem,seg
;np. MOV [1234],DS
MOV seg,reg
;np. MOV DS,AX
MOV seg,mem
20
Specjalne rozkazy przesłania
Przesłanie bajtu z DS:SI do ES:DI
MOVSB
Przesłanie słowa z DS:SI do ES:DI
MOVSW
Umieszczenie zawartości rejestru, wartości
stałej lub komórki pamięci na stosie
PUSH AX
PUSH 09h
PUSH [0387h]
przesłanie flag na stos
PUSHF
ładowanie z DS:SI do AL
LODSB
ładowanie z DS:SI do AX
LODSW
21
Specjalne rozkazy przesłania
pobranie ze stosu do rejestru lub
komórki pamięci
POP reg
POP mem
pobranie ze stosu znaczników
POPF
prześlij bajt z AL do ES:DI
STOSB
prześlij słowo z AX do ES:DI
STOSW
pobranie danej z portu do
IN acc,stala
IN AX,DX
wyprowadzenie danej na port
OUT 20h,AL
OUT DX,AX
22
Specjalne rozkazy przesłania
ładowanie adresu efektywnego
LEA DX, tablica
pobranie do AH rejestru znaczników
LAHF
przesłanie AH do rejestru znaczników
SAHF
zamiana danych miejscami
XCHG reg,reg
XCHG reg,mem
XCHG mem,reg
pobranie elementu z tablicy
o adresie DS:BX do AL
XLAT
pobranie adresu z jednoczesnym
załadowaniem rejestru DS (ES) i
podanego rejestru
LDS reg,mem
LES reg,mem
23
Rozkazy arytmetyczne
dodanie arytmetyczne zawartości dwóch rejestrów lub komórek
pamięci 8 lub 16 bitowo
ADD reg1,reg2
reg1 = reg1 + reg2
ADD reg, [mem]
reg = reg + [mem]
ADD [mem], reg
[mem] = [mem] + reg
ADD reg, stała
reg = reg + stala
ADD [mem], stała
[mem] = [mem] + stala
24
Rozkazy arytmetyczne
dodanie arytmetyczne zawartości dwóch rejestrów i znacznika
przeniesienia (8 lub 16 bitowo)
ADC reg,reg
ADC mem,reg
ADC reg,mem
ADC reg,stała
ADC mem,stała
odejmowanie arytmetyczne zawartości dwóch rejestrów (8 lub 16
bitowo) lub kombinacji rejestrów i pamięci
SUB reg,reg
SUB reg,mem
SUB mem,reg
SUB reg,stała SUB mem,stała
25
Rozkazy arytmetyczne
odejmowanie arytmetyczne zawartości dwóch rejestrów lub
komórek pamięci z pożyczką (bit Carry) 8 lub 16 bitowo
SBB reg,reg
SBB mem,reg
SBB reg,mem
SBB reg,stała
SBB mem,stała
Inkrementacja lub dekrementacja rejestru lub komórki pamięci
INC reg
DEC reg
INC mem
DEC mem
zmiana znaku liczby w rejestrze lub komórce pamięci
NEG reg
NEG mem
26
Operacje arytmetyczne
korekta wyniku po dodaniu dwóch liczb w spakowanym lub
rozpakowanym kodzie BCD (16-bitowych lub 8 bitowych).
MOV BX,0207H
MOV AX,0405H
ADD AX,BX
AAA ; poprawka dziesiętna po dodawaniu w rozpakowanym kodzie BCD
MOV AX,0405H
ADD AX,BX
DAA ; poprawka dziesiętna po dodawaniu w spakowanym kodzie BCD
27
Operacje arytmetyczne
korekta wyniku po odjęciu dwóch liczb w spakowanym lub
rozpakowanym kodzie BCD (16-bitowych lub 8 bitowych).
MOV AX,0505H
MOV BX,0207H
SUB AX,BX
AAS
MOV AX,0505H
SUB AX,BX
DAS
28
Operacje arytmetyczne
MUL - mnożenie liczb bez znaku.
Operacja 8-bitowa pobiera pierwszy argument z AL, wynik przekazywany
jest do AX.
Operacja 16-bitowa pobiera argument z AX, wynik przekazywany jest do
pary rejestrów AX i DX.
Operacja 16-bitowa pobiera argument z AX, wynik przekazywany jest do
pary rejestrów AX i DX.
Mnożenie ze znakiem realizowane jest przez IMUL
MUL BX
MUL mem
IMUL CL
;DX:AX=AX*BX
;DX:AX=AX*[mem]
;AX = AL*CL
29
Operacje arytmetyczne
DIV dzielenie liczb bez znaku.
Operacja dzielenia przez dzielnik 8-bitowy pobiera pierwszy
argument z AX.
Operacja dzielenia przez dzielnik 16-bitowy pobiera argument z pary
rejestrów AX i DX (DX jest starszym słowem wyniku).
Dzielenie ze znakiem realizowane jest przez IDIV
DIV reg ; dzielenie przez daną z rejestru
DIV mem ; dzielenie przez daną z komórki pamięci
IDIV reg ; dzielenie liczb ze znakiem przez rejestr
IDIV mem ; dzielenie przez zawartość komórki pamięci
30
Operacje arytmetyczne
Konwersje
AAD - instrukcja konwersji liczby w rozpakowanym kodzie BCD, znajdującej się
w rejestrach AH i AL., na liczbę binarną.
AAM instrukcja konwersji liczby binarnej z rejestru AX na rozpakowany kod
BCD, do rejestrów AH i AL.
MOV AX,52H ;
AAM
CBW przekształcenie bajtu w AL na słowo w AX z uwzględnieniem znaku liczby
MOV AL,80H ; DZIESIĘTNIE JEST TO -128
CBW
; AX=FF80H
CWD przekształcenie słowa w AX na podwójne słowo (zapisane w parze
rejestrów AX i DX).
MOV AX,8000H ; DZIESIĘTNIE JEST TO -32768
CWD ; AX=8000H, DX=FFFFH,
31
Operacje logiczne i bitowe
OR - suma logiczna lub bitowa argumentów: rejestry, pamięć, stała
OR reg,reg
OR reg,stała
OR reg,mem
OR mem,reg
OR mem,stała
Wynik operacji umieszczany jest w pierwszym argumencie
XOR różnica symetryczna argumentów. Składnia jak dla instrukcji
OR.
Przykład:
XOR reg, reg
Szybki sposób na wyzerowanie zawartości rejestru (intrukcja XOR
jest znacznie szybsza niż MOV)
32
Operacje logiczne i bitowe
AND - iloczyn bitowy argumentów: rejestry, pamięć, stała
AND reg,reg
AND reg,mem
AND reg,stala
AND mem,stała
AND mem,reg
Wynik jest zapamiętywany w pierwszym argumencie
TEST – iloczyn bitowy argumentów. Instrukcja ta wykonuje logicznąoperację AND
na swoich argumentach. Wynik nie jest nigdzie zapamiętywany, ale na jego
podstawie ustawiane są flagi.
TEST reg,reg
TEST reg,mem
TEST reg,stala
TEST mem,stała
TEST mem,reg
NOT - negacja każdego bitu liczby (w rejestrze lub pamięci)
33
Przesunięcia bitowe
SHL - przesunięcie logiczne w lewo,
najstarszy bit przechodzi do CF, a
najmłodszy bit jest uzupełniany zerem
SHL mem, 1
SHL reg, 1
SHL mem, cl
SHL reg, cl
SHR - przesunięcie logiczne w prawo,
najmłodszy bit przechodzi do CF, a
najstarszy bit jest uzupełniany zerem.
Składnia i argumenty jak dla SHL.
; przesunięcie logiczne komórki pamięci o 1 w lewo
;
; od 80286
; przesunięcie logiczne komórki rejestru o zawartość CL w lewo
SAL - przesunięcie arytmetyczne w lewo
= SHL. Operacja równoważna z
mnożeniem przez 2.
SAR - przesunięcie arytmetyczne w
prawo. Operacja równoważna z
dzieleniem przez 2. Najbardziej znaczący
bit posiada taka wartość jak przed
przesunięciem – znak liczby
SAL
SAL
SAL
SAL
SAR
SAR
SAR
SAR
mem,1
reg,1
mem,CL ;
reg,CL
mem,1
reg,1
mem,Cl ; od 80286
reg,cl
34
Przesunięcia bitowe
ROL - obrót w lewo. Składnia jak dla rozkazów SHL, SHR, SAL, SHR,
przy czym bit najbardziej znaczący jest przesuwany zarówno do CF
jak i do bitu najmłodszego
ROR - obrót w prawo. Składnia jak dla rozkazów SHL, SHR, SAL,
SHR, przy czym bit najmłodszy jest przesuwany zarówno do CF jak i
do bitu najstarszego
RCL - obrót w lewo z uwzględnieniem bitu Carry (CF). Najbardziej
znaczący bit jest przesuwany do CF, a CF do bitu najmłodszego
Składnia jak dla rozkazów SHL, SHR, SAL, SHR.
RCR - obrót w prawo z uwzględnieniem bitu Carry. Najmniej
znaczący bit jest przesuwany do CF, a CF do bitu najstarszego.
Składnia jak dla rozkazów SHL, SHR, SAL, SHR.
35
JE/JZ - skok, gdy równy/równy zero
Rozkazy skoków
JL/JNGE - skok, gdy mniejszy/nie równy lub nie większy
JLE/JNG - skok, gdy mniejszy lub równy/nie większy
JB/JNAE - skok, gdy mniejszy/nie większy lub nie równy
JBE/JNA - skok, gdy mniejszy lub równy/nie większy
JP/JPE - skok, gdy parzysta/nieparzysta
JO - skok, gdy nadmiar (przepełnienie)
JS - skok, gdy znak ujemny
JNE/JNZ - skok, gdy nie równy/nie zero
JNL/JGE - skok, gdy nie mniejszy/większy lub równy
JNLE/JG - skok, gdy nie mniejszy lub równy/większy
JNB/JAE - skok, gdy nie mniejszy/większy lub równy
JNBE/JA - skok, gdy nie mniejszy lub równy/większy
JNP/JPO - skok, gdy nieparzystość/parzystość nieparzysta
JNO - skok, gdy nie ma nadmiaru
JNS - skok, gdy znak dodatni
JC - skok, gdy CF=1
JNC - skok, gdy CF=0
36
Skoki do podprogramów i pętle
CALL nazwa_podprogramu ; skok do podprogramu (wywołanie procedury)
JMP - skok bezwarunkowy
RET ; powrót z podprogramu (procedury)
LOOP - zmniejsza CX o 1 i wykonuje skok, gdy CX > 0.
LOOP nazwa_etykiety ; skok do etykiety, gdy CX > 0
LOOPZ/ LOOPE - jak LOOP, tylko może wykonać dodatkowo skok, gdy bit zera (ZF) jest
ustawiony.
LOOPNZ/LOOPNE - jak LOOP, tylko może wykonać dodatkowo skok, gdy bit zera nie jest
ustawiony.
JCXZ - rozkaz skoku warunkowego, który jest wykonywany, gdy CX jest równy zero
Należy uważać z modyfikacją rejestru CX, gdyż jest on licznikiem pętli.
Zasięg skoków jest ograniczony do -128 +127 bajtów. Etykieta, do której wykonywany
jest skok powinna się znajdować; na ogół powyżej instrukcji kontroli iteracji.
37
Typowa pętla
MOV CX,10
Tu:
...............
............... ; ciąg instrukcji w pętli
...............
LOOP Tu
Powyższa pętla zostanie wykonana 10 razy.
Należy uważać z modyfikacją rejestru CX, gdyż jest on
licznikiem pętli.
Zasięg skoków jest ograniczony do -128 +127 bajtów.
Etykieta, do której wykonywany jest skok powinna się
znajdować na ogół powyżej instrukcji kontroli iteracji.
38
Rozkazy łańcuchowe
Rozkazy łańcuchowe operują na ciągach danych bajtowych lub słowowych.
Ciągi te mogą mieć długość do 128 KB.
Po wykonaniu rozkazu łańcuchowego rejestry SI i DI są automatycznie
zmieniane, aby przygotować je do zaadresowania następnego elementu
łańcuchowego.
Gdy flaga DF (direct flag) = 1, zawartość tych rejestrów jest zwiększana, gdy
zero jest zmniejszana.
Gdy elementy łańcucha są bajtami wartość SI i DI jest zmniejszana o 1, a
gdy słowami - o 2.
Po zrealizowaniu rozkazu łańcuchowego wartość CX jest zmniejszana o 1.
Przed rozkazem łańcuchowym należy wpisać odpowiednią liczbę do CX
określającą liczbę powtórzeń rozkazu łańcuchowego.
Powtórzenia wykonuje się za pomocą rozkazów REP.
Gdy CX=0 to zostaje przerwane powtarzanie rozkazów łańcuchowych i
program przechodzi do wykonania kolejnego rozkazu.
39
Rozkazy łańcuchowe
REP – powtórz
REPE – powtórz dopóki równe
REPZ – powtórz dopóki zero
REPNZ – powtórz dopóki nie zero
REPNE – powtórz dopóki nie równe
Przykład:
MOV CX,10 ;
REP STOSW ; 10 razy z AX do ES:DI
MOVSB ; przesłanie bajtu z DS:SI do ES:DI
MOVSW ; przesłanie słowa
LODSB ; ładowanie z DS:SI do AL
LODSW ; ładowanie z DS:SI do AX
40
Rozkazy łańcchowe
STOSB ; prześlij bajt z AL do ES:DI
STOSW ; prześlij słowo z AX do ES:DI
CMPS [seg:]argument, argument; porównanie bajtów
CMPSB ; porównanie bajtów z DS:SI i ES:DI
CMPSW ; słów
SCAS [seg:]argument ; porównanie bajtu lub słowa wskazywanego
przez ES:DI z daną, która znajduje się w akumulatorze (AL lub AX) –
po odejmowaniu ustawiane są znaczniki
SCASB ; porównanie bajtów
SCASW ; porównanie słów
41
Rozkazy sterowania procesem
CLC ; zerowanie znacznika CF
CMC ; zmiana stanu CF na przeciwny
STC ; ustawienie znacznika CF
CLD ; zerowanie znacznika DF (direct flag)
STD ; ustawienie znacznika DF
CLI ; zerowanie znacznika IF (interrupt flag)
STI ; ustawienie znacznika IF
WAIT ; wprowadzenie procesora w stan oczekiwania
NOP ; nic nie rób
LOCK ; blokada dostępu do magistrali
42
Rodzaje adresowania 8086
Natychmiastowe
MOV AX,1234H
Bezpośrednie
MOV AX,BX
MOV AH,[1234]
Pośrednie – przez rejestr bazowy
MOV
MOV
MOV
MOV
MOV
CX,1234H
BX,8
BP,2
[BP],CX ; SS:BP
AX,[BX] ; DS:BX
43
Rodzaje adresowania 8086
Pośrednie przez rejestr bazowy i przemieszczenie
MOV
MOV
MOV
MOV
MOV
CX,1234H
BX,8
BP,2
[BP+1],CX ; SS:BP+1
AX,[BX+2] ; DS:BX+2
Pośrednie przez rejestr indeksowy
MOV
MOV
MOV
MOV
DI,3
SI,7
AX,[SI] ; DS:SI
[DI],BX ; ES:DI
44
Rodzaje adresowania 8086
Pośrednie przez rejestr indeksowy i przemieszczenie
MOV
MOV
MOV
MOV
DI,3
SI,7
AX,[SI+5] ; DS:SI+5
[DI+3],BX ; ES:DI+3
Pośrednie przez rejestr bazowy, indeksowy i przemieszczenie
MOV
MOV
MOV
MOV
MOV
MOV
MOV
MOV
SI,3
BX,2
BP,1
DI,4
DX,45
[BP+DI+4],DX ; SS:BP+DI+4
AX,[BX+SI+1] ; DS:BX+SI+1
CX,[DI+BP+1] ; SS:DI+BP+1
45
Rodzaje adresowania 8086
Adresowanie łańcuchowe
MOV AX,0H
MOV DS,AX
MOV SI,0H
MOV AX,9000H
MOV ES,AX
MOV DI,0H
MOV CX,1024D
CLD ; jeśli DF = 0 to inkrementacja
PETLA: MOVSB ; przesłanie z DS:SI do ES:DI
LOOP PETLA ;
46
Adresowanie układów
wejścia i wyjścia
IN acc, stala ; pobranie danej z portu do akumulatora, np.
IN AX, 3f8h
IN acc, DX
OUT port, acc ; wyprowadzenie danej na port np.
OUT 20h, AL
OUT DX, AX
47
Makroinstrukcje a podprogramy
Podprogram to sekwencja rozkazów, która raz umieszczona w
pamięci może być wykonywana wielokrotnie w różnych miejscach
programu głównego.
Dla skrócenia zapisów programów w języku asembler wprowadzono
makroinstrukcje, czyli symboliczne oznaczenia odpowiadające nie
pojedynczym rozkazom, lecz sekwencjom rozkazów.
Podczas tłumaczenia programu, makroinstrukcje są tłumaczone na
odpowiadające im ciągi rozkazów.
WYSWIETL_ZNAK MACRO
MOV AH,02H
INT 21H
ENDM
48
Makra
GOTO_XY MACRO x,y
MOV AH,2
MOV DL,X
MOV BH,0
MOV DH,Y
START:
INT 10H
MOV AX,DATA
ENDM
MOV DS,AX
GOTO_XY 2,3
MOV DL,’0’
WYSWIETL_ZNAK
KONIEC:
MOV AH,4CH
INT 10H
END START
49
Przykład programu
.MODEL SMALL
.DATA
pusta_linia DB 13,10,’$’
iloraz DB ?
reszta DB ?
dzielnik DB 10
.CODE
START:
MOV AX,@DATA
MOV DS,AX
XOR AX,AX ; zerowanie AX
XOR DX,DX
XOR CX,CX
MOV BX,12d ; ilość liczb do zsumowania
50
Przykład
Petla:
INC CX
ADD AX,CX
PUSH AX
DIV dzielnik ; AX / dzielnik-> AL, reszta ->AH
MOV [iloraz],AL
MOV [reszta],AH
CALL ILORAZY
CALL RESZTY
CALL LINIA
POP AX
CMP CX,BX
JNE Petla
JMP Koniec
Koniec:
MOV AH,4CH
INT 21H
END START
51
Przykład
;********************PROCEDCURY**************
ILORAZY PROC NEAR
MOV AH,2
MOV DL,[Iloraz]
ADD DL,48
INT 21H
;***********************************
RET
RESZTY PROC NEAR
ILORAZY ENDP
MOV AH,2
MOV DL,[reszta]
ADD DL,48
INT 21H
;**************************
RET
LINIA PROC NEAR
RESZTY ENDP
MOV AH,09
MOV DX,OFFSET pusta_linia
INT 21H
RET
LINIA ENDP
;**************************
52
Koprocesor matematyczny
Intel 8087
53
Budowa koprocesora
Procesor 8086 wykonuje działania tylko na liczbach całkowitych
Koprocesor (FPU = Floating Point Unit, NPX = Numerical Processor
eXtension) służy do wykonywania działań matematycznych na
liczbach zmiennoprzecinkowych
Do procesorów 8086, 80286, 80386 koprocesory były dołączane
jako osobne układy: 8087, 80287, 80387
Od wersji Intel 486DX koprocesor był już na jednym chipie z
procesorem. Tak jest do dzisiaj.
Współczesne procesory posiadają bardzo szybki koprocesor, szybszy
w obliczeniach od samego procesora. Przykładowo obliczenie
5,123456 * 3,123456 zajmie mniej czasu na koprocesorze niż
obliczenie 5 * 3 za pomocą procesora.
54
Architektura koprocesora
55
Podstawowe rejestry koprocesora
Stos rejestrów (ang. register stack) – zbiór 80-bitowych rejestrów roboczych R7-R0, w
którym jest zorganizowany stos ST.
Z każdym rejestrem Rx jest związane dwubitowe pole (ang. tag) wskazujące na rodzaj
danych:
•liczba znormalizowana,
•zero,
•wartość specjalna (NaN, nieokreślona, Inf, liczba zdenormalizowana),
•rejestr pusty.
Rejestr stanu (znaczników) (ang. status register) – określa aktualny stan FPU i zawiera:
•znaczniki wystąpienia wyjątku (ang. exception flags),
•flagę zajętości (ang. busy),
•numer rejestru R7-0 skojarzony z wierzchołkiem stosu ST(0) (ang. TOP),
•flagi C3-0 o znaczeniu zależnym od instrukcji, np. jako flagi CF (przeniesienia), ZF
(zera), PF (parzystości).
Jednostka zmiennoprzecinkowa FPU x87 posiada osiem 80-bitowych rejestrów R7-R0.
Rozkazy FPU traktują te rejestry jak stos, gdzie operacja odnosi się zawsze do jego
wierzchołka, oznaczanego ST(0).
56
Przykład obliczenia
57
Odwrotna notacja polska
Reverse Polish Notation, RPN W zapisie tym argumenty działania
zapisuje przed symbolem tego działania.
Zapis tradycyjny
Zapis ONP
a+b
ab+
a+b+c
ab+c+
c+b+a
cb+a+
(a+b)*c
ab+c*
c*(a+b)
cab+*
(a+b)*c+d
ab+c*d+
(a+b)*c+d*a
ab+c*da*+
(a+b)*c+d*(a+c)
ab+c*dac+*+
(a+b)*c+(a+c)*d
ab+c*ac+d*+
(2+5)/7+3/5
25+7/35/+
58
ONP a koprocesor
ONP mówi o kolejności działań, jakie należy wykonać na
koprocesorze.
(a+b)*c+(a+c)*d
->
a b + c * a c + d * +
fld [a]
fld [b]
faddp
fld [c]
fmulp
fld [a]
fld [c]
faddp
fld [d]
fmulp
faddp
;Teraz st0 jest równe wartości całego wyrażenia.
59
ONP - ćwiczenia
Zamień na ONP:
a/c/d + b/c/d
a/(c*d) + b/(c*d)
(a+b)/c/d
(a+b)/(c*d)
Zamień z ONP na zapis tradycyjny :
ab*cd*e/a5/c7/ed-9/*+
a3+b/de+6^dc-7b*2^/
60
Instrukcje koprocesora
Instrukcje przemieszczenia danych:
FLD/FILD [mem] - załaduj liczbę rzeczywistą/całkowitą z pamięci. Dla
liczby rzeczywistej jest to 32, 64 lub 80 bitów. Dla całkowitej - 16, 32 lub
64 bity.
FST [mem32/64/80] - do pamięci idzie liczba ze st(0).
FSTP [mem32/64/80] - zapisz st(0) w pamięci i zdejmij je ze stosu. Znaczy
to tyle, że st(1) o ile istnieje, staje się st(0) itd. każdy rejestr cofa się o 1.
FIST [mem16/32] - ewentualnie obciętą do całkowitej liczbę z st(0) zapisz
do pamięci.
FISTP [mem16/32/64] - jak wyżej, tylko ze zdjęciem ze stosu.
FXCH st(i) - zamień st(0) z st(i).
61
Instrukcje koprocesora
Instrukcje ładowania stałych:
FLDZ - załaduj zero. st(0) = 0.0
FLD1 - załaduj 1. st(0) = 1.0
FLDPI - załaduj pi.
FLDL2T - załaduj log2(10)
FLDL2E - załaduj log2(e)
FLDLG2 - załaduj log(2)=log10(2)
FLDLN2 - załaduj ln(2)
62
Instrukcje koprocesora
Działania matematyczne:
dodawanie:
FADD, składnia identyczna jak w odejmowaniu prostym
odejmowanie:
FSUB [mem32/64]
st := st-[mem]
FSUB st(0),st(i)
st := st-st(i)
FSUB st(i),st(0)
st(i) := st(i)-st(0)
FSUBP st(i), st(0)
st(i) := st(i)-st(0) i zdejmij
FSUBP (bez argumentów) = FSUBP st(1),st(0)
FISUB [mem16/32int]
st := st-[mem]
odejmowanie odwrotne
FSUBR [mem32/64]
st := [mem]-st(0)
FSUBR st(0),st(i)
st := st(i)-st(0)
FSUBR st(i),st(0)
st(i) := st(0)-st(i)
FSUBRP st(i),st(0)
st(i) := st(0)-st(i) i zdejmij
FSUBRP (bez argumentów) = FSUBRP st(1),st(0)
FISUBR [mem16/32int]
st := [mem]-st
63
Instrukcje koprocesora
Działania matematyczne:
mnożenie:
FMUL, składnia identyczna jak w odejmowaniu prostym.
dzielenie:
FDIV, składnia identyczna jak w odejmowaniu prostym.
dzielenie odwrotne:
FDIVR, składnia identyczna jak w odejmowaniu odwrotnym.
wartość bezwzględna:
FABS (bez argumentów) zastępuje st(0) jego wartością
bezwzględną.
zmiana znaku:
FCHS:
st(0) := -st(0).
pierwiastek kwadratowy:
FSQRT: st(0) := SQRT[ st(0) ]
reszty z dzielenia:
FPREM, FPREM1
st(0) := st(0) mod st(1).
zaokrąglanie do liczby całkowitej:
FRNDINT: st(0) := (int)st(0).
64
Instrukcje koprocesora
Komendy porównania:
FPU oprócz rejestrów danych zawiera także rejestr kontrolny (16 bitów) i rejestr
stanu (16 bitów).
W rejestrze stanu są 4 bity nazwane C0, C1, C2 i C3.
To one wskazują wynik ostatniego porównania, a układ ich jest taki sam, jak flag
procesora, co pozwala na ich szybkie przeniesienie do flag procesora.
Aby odczytać wynik porównania, należy:
fcom
fstsw ax
sahf ; AH -> flagi
i używać normalnych komend JE, JB itp
65
Instrukcje koprocesora
Komendy porównania:
FCOM st(n)/[mem] - porównaj st(0) z st(n) (lub zmienną w pamięci) bez
zdejmowania st(0) ze stosu FPU
FCOMP st(n)/[mem] - porównaj st(0) z st(n) (lub zmienną w pamięci) i zdejmij
st(0)
FCOMPP - porównaj st(0) z st(1) i zdejmij oba ze stosu
FICOM [mem] - porównaj st(0) ze zmienną całkowitą 16- lub 32-bitową w pamięci
FICOMP [mem] - porównaj st(0) ze zmienną całkowitą 16- lub 32-bitową w
pamięci, zdejmij st(0)
FCOMI st(0), st(n) - porównaj st(0) z st(n) i ustaw flagi procesora, nie tylko FPU
FCOMIP st(0), st(n) - porównaj st(0) z st(n) i ustaw flagi procesora, nie tylko FPU,
66
zdejmij st(0)
Instrukcje koprocesora
Specjalne funkcje matematyczne
Instrukcje trygonometryczne:
FSIN - st(0) := sinus [st(0)]
FCOS - st(0) := kosinus [st(0)]
FSINCOS - st(0) := kosinus [st(0)], st(1) := sinus [st(0)]
FPTAN - partial tangent = tangens st(0) := tg [st(0)]
FPATAN - arcus tangens st(0) := arctg [st(0)]
Logarytmiczne, wykładnicze:
FYL2X
FYL2XPI
F2XM1
st(1) := st(1)*log2[st(0)] i zdejmij
st(1) := st(1)*log2[ st(0) + 1.0 ] i zdejmij
st(0) := 2^[st(0)] - 1
67
Przykłady FPU
program wyświetlający częstotliwość zegara
dzielna DQ 1234DDh ; 4013 91a6 e800 0000 0000
dzielnik DQ 10000h
iloraz DT ?
mov ax, @data
mov ds, ax
mov es, ax ; inicjujemy segmenty
finit ; uruchamiamy koprocesor
fild qword ptr [dzielna] ; ładujemy dzielną. st(0) = 1234DD
fild qword ptr [dzielnik] ;
;
fdivp
;
;
fstp tbyte ptr [iloraz]
ład. dzielnik. st(0) = 10000h,
st(1) = 1234DD
dzielimy. st(1) := st(1)/st(0) i
zdejmij. st(0) ~= 18.2
; zapisujemy st(0) do pamięci i
; zdejmujemy ze stosu
68
Przykłady FPU
czy sinus liczby PI rzeczywiście jest równy 0 (w procesorze)?
finit
fldpi ; wczytujemy PI
fsin ; obliczamy sin(PI)
ftst ; porównujemy st(0) z zerem.
fstsw ax ; zapisujemy rejestr stanu bezpośrednio w AX.
mov ah,9 ; AH=9, flagi niezmienione
je jest_zero ; st(0) = 0? Jeśli tak, to wypisz, że jest
Niestety nie jest to zero.
69
Przykłady FPU
czy pierwiastek z 256 rzeczywiście jest równy 16?
dwa_pie_sze dw 256
szesnascie dw 16
finit
mov ax,cs
mov ds,ax
fild word ptr [dwa_pie_sze] ; st(0) = 256
fsqrt ; st(0) = sqrt(256)
fild word ptr [szesnascie] ; st(0) = 16, st(1) = sqrt(256)
fcompp ; porównaj st(0) i st(1), zdejmij oba
; st: [pusty]
fstsw ax
sahf
mov ah,9
je etykieta ;TUTAJ SKOCZ, JEŚLI WARUNEK JEST SPELNIONY
70
Przykłady FPU
czy 400 jest kwadratem liczby całkowitej
finit
mov ax,cs
mov ds,ax
czterysta dw 400
fild word ptr [czterysta] ; st: 400
fsqrt ; st: sqrt(400)
fld st(0) ; do st(0) wczytaj st(0).
; st: sqrt(400), sqrt(400)
frndint ; zaokrąglij do liczby całkowitej.
; st: (int)sqrt(400), sqrt(400)
fcompp ; porównaj i zdejmij oba.
fstsw ax
sahf
mov ah,9
je tak400 ; skocz do petli jeżeli tak
71