instrukcja TM cw02 ASM, Technikum, Assembler
[ Pobierz całość w formacie PDF ]
Laboratorium przedmiotu Technika Mikroprocesorowa
ćw. 2: Wprowadzenie do asemblera x86, system przerwań
Asembler x86:
Asembler jest to język programowania, naleŜący do języków niskiego poziomu.
Znaczy to tyle, Ŝe jednej komendzie asemblera odpowiada dokładnie jeden rozkaz
procesora. Asembler operuje na rejestrach procesora. Do naszych celów będziemy
wykorzystywać 16-bitowe rejestry ogólnego przeznaczenia (AX, BX, CX, DX) oraz
wybrane 16-bitowe rejestry indeksowe, wskaźnikowe i segmentowe. W celu badania
wyników operacji (logicznych lub arytmetycznych) wykorzystamy rejestr stanu
procesora.
Aby pierwsze spotkanie z asemblerem nie było zbyt trudne nasze programy
asemblerowe będziemy umieszczać jako cześć kodu projektu napisanego w języku
C++. W związku z tym wszelka notacja będzie taka jak w języku C++!!
Wykorzystywanym środowiskiem będzie Microsoft Visual Studio .NET oraz Borland
C++ 3.1.
W celu umieszczenia kodu asemblera w języku C++ stosujemy polecenie
__asm
.
Aby uŜywać zmiennych w programie moŜemy je zadeklarować zgodnie ze składnią
języka C++ (naleŜy uwaŜać na typ zmiennej). KaŜdy z rejestrów 16-bitowych
moŜemy wykorzystać poprzez odwołanie bezpośrednio do ich 8-bitowych części
górnej lub dolnej (np. rejestr CX dzieli się na część starszą CH i młodszą CL).
00000000 | 00000000
CX(16b)
CH(8b) | CL(8b)
Chcąc wykorzystać pętle w programie posłuŜymy się skokami warunkowymi do
miejsc
oznaczonych
etykietami.
Przykładowy
kod
programu
z
opisem
jest
przedstawiony poniŜej:
int main (void)
{
unsigned short int Liczba1 = 0x1;
//liczba 16-bitowa
unsigned char
Liczba2;
//liczba 8-bitowa
__asm {
push AX;
push BX;
push CX;
mov AL, 0x22;
mov AH, 3;
and AX, 0x00FF;
add AX, 10;
mov BX, Liczba1;
skok:
sub AX, BX;
jnz skok;
pop CX;
pop BX;
pop AX;
…
}
return 0;
}
deklarujemy 2 zmienne
Liczba1
i
Liczba2
(przedstawiony sposób deklaracji
typów całkowitych 8 i 16 bitowych bez znaku);
3 instrukcje
push
słuŜą do zapisania na stosie kolejnych rejestrów, gdyŜ bedą
one w programie modyfikowane;
do rejestru AL zapisujemy szesnastkową wartość 0x22, czyli 34 dziesiętnie
(zauwaŜmy, Ŝe rejestr AL jest 8 – bitowy);
do rejestru AH zapisujemy dziesiętną wartość 3. W efekcie dwóch powyŜszych
operacji rejestr AX zawiera 3*256+34 = 802 dziesiętnie, czyli 0x0322
szesnastkowo;
wykonujemy operację logiczną
and
na wartościach 0x00FF i rejestrze AX,
wynik zapisujemy do AX. W wyniku tej operacji wyzerowana zostanie starsza
część rejestru AX. Teraz AX zawiera 0x0022 szesnastkowo;
dodajemy do AX 10, AX zawiera 44 dziesiętnie;
do rejestru BX wpisujemy zawartość zmiennej
Liczba1
, czyli 1;
od AX odejmujemy BX i wynik zapisujemy w AX (w naszym przypadku będzie
to zmniejszanie o 1)
jeŜeli wynik ostatniej operacji był niezerowy (instrukcja
jnz
) to skaczemy do
etykiety
skok
i wykonujemy kolejne odejmowanie, powtarzamy tą część
programu aŜ do momentu wyzerowania AX, czyli u nas 44 razy;
pobieramy ze stosu (
pop
) wcześniej zapisane tam wartości (w odwrotnej
kolejności niŜ je zapisywaliśmy!!)
Przerwania:
Przerwanie jest to zatrzymanie wykonującego się w danej chwili programu i
przekazanie sterowania do procedury, która to przerwanie obsługuje. Po
zakończeniu się tej procedury następuje powrót do wcześniej wykonywanego
programu. Istnieją dwa rodzaje przerwań: przerwania sprzętowe i systemowe.
Przerwania sprzętowe wywoływane są w krytycznych sytuacjach (na Ŝądanie
urządzeń zewnętrznych). Ze względu na to, Ŝe w jednej chwili moŜe zgłosić kilka
urządzeń Ŝądanie o przerwanie, a procesor w danej chwili moŜe obsłuŜyć tylko jedno
z nich, kaŜdemu przerwaniu sprzętowemu przyporządkowano pewien numer
(priorytet). Numer ten mówi w jakiej kolejności naleŜy wykonywać przerwania.
Przerwania sprzętowe mogą być maskowalne lub nie. Przerwania maskowalne nie
muszą być przekazywane do procesora w przeciwieństwie do przerwań
niemaskowalnych. Przerwania systemowe mogą być wywoływane tylko w sposób
programowy.
W naszych programach wykorzystamy systemowe przerwania DOS. Nie moŜna
wywołać tych przerwań umieszczając wstawkę asemblerową w kodzie C++. Dlatego
przerwania wywoływać będziemy z poziomu języka C++ w środowisku Borland C++
3.1. Przykład programu wyświetlającego tekst (uŜycie przerwania DOS 0x21):
int main (void)
{
char Napis[] = “Moj napis!$”;
struct REGPACK reg;
reg.r_ax = 0x0900;
reg.r_dx = FP_OFF(napis);
reg.r_ds = FP_SEG(napis);
intr(0x21, ®);
return 0;
}
definiujemy zmienną
Napis
i strukturę
reg
przechowującą interesujące nas
rejestry;
Wpisujemy odpowiednie wartości do rejestrów, AH zawiera numer funkcji
przerwania 0x21 (funkcja nr. 9 – czyli wyświetlanie tekstu), DX i DS zawierają
adres napisu w pamięci w formacie segment:offset – poniewaŜ pracujemy w
C++ musimy uŜyć fukcji
FP_OFF
i
FP_SEG
;
wywołujemy przerwanie przy określonych wartościach rejestrów, w wyniku
tego nasz napis zostanie wyświetlony;
Sposoby dost
ę
pu do portów:
W systemach Windows nowszych niŜ Windows 98 zabroniony jest dostęp
uŜytkownika do urządzeń I/O. JeŜeli chcemy pod takim systemem uruchamiać
program odwołujący się do urządzeń I/O naleŜy odblokować dostęp do urządzeń I/O.
Jedną z metod odblokowania go jest zastosowanie sterownika, np. giveio.sys
(np:
). Po zainstalowaniu
go naleŜy załączyć odpowiednie fragmenty kodu do programu:
- jeŜeli program pisany jest pod DOS:
--------------------------------------------------------------
int f = open("\\\\.\\giveio", O_CREAT, S_IREAD);
close(f);
--------------------------------------------------------------
- jeŜeli program pisany jest pod WINDOWS:
--------------------------------------------------------------
HANDLE h;
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(h == INVALID_HANDLE_VALUE)
{
printf("Couldn't access giveio device\n");
return -1;
}
CloseHandle(h);
--------------------------------------------------------------
oraz dołączyć biblioteki, odpowiednio fcntl.h i sys/stat.h dla DOSa oraz windows.h dla
Windowsa.
Przebieg
ć
wiczenia:
Celem ćwiczenia jest zapoznanie studenta z praktycznym programowaniem w języku
asembler x86.
Przygotowanie do laboratorium:
praktyczna znajomość języka „C++”;
umiejętność wykonywania operacji logicznych i arytmetycznych na liczbach
zapisanych w róŜnych systemach liczbowych;
podstawowa znajomość sposobu pisania kodu w asemblerze;
rozumienie pojęć: przerwanie, obsługa przerwania itp.;
linki;
Przebieg ćwiczenia i sposób oceniania:
kartkówka (max. 2 pkt);
szybkie zapoznanie ze środowiskiem programowania;
poznanie i zrozumienie podstawowych instrukcji asemblera x86;
stosowanie
poznanych
instrukcji
do
realizacji
prostych
programów
asemblerowych - wstawki asemblerowe w kodzie C++ (max 1 pkt);
realizacja bardziej zaawansowanego programu asemblerowego (max 1 pkt);
realizacja wybranych programów w oparciu o przerwania DOS (max 1 pkt);
* podczas ćwiczenia kaŜda sekcja tworzy osobny protokół z przebiegu ćwiczenia
Protokół:
Protokół powinien zawierać:
nazwiska osób wykonujących ćwiczenie;
tytuł i numer ćwiczenia;
poprawny numer grupy i sekcji;
komentarze przedstawiające postęp w realizacji ćwiczenia;
Literatura:
- kurs asemblera
- kurs asemblera, przerwania
- podstawy asemblera, lista instrukcji
...
Opracowanie: Mariusz Latos, 2007
[ Pobierz całość w formacie PDF ]