DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz czytać Dzwon?
Bez spamu

Programowanie na poziomie instrukcji maszynowych to minimalny poziom, na którym możliwe jest programowanie. System instrukcji maszynowych musi być wystarczający do wykonywania wymaganych czynności, wydawania instrukcji do sprzętu komputera.

Każda instrukcja obsługi maszyny składa się z dwóch części:

  • sala operacyjna – ustalanie „co robić”;
  • operand - definiowanie obiektów przetwarzania, "co z tym zrobić".

Instrukcja maszynowa mikroprocesora napisana w języku asemblera to pojedyncza linia o następującej formie składniowej:

etykieta polecenia/dyrektywy argument(y); komentarze

W takim przypadku wymaganym polem w wierszu jest polecenie lub dyrektywa.

Etykieta, polecenie/dyrektywa i operandy (jeśli występują) są oddzielone co najmniej jedną spacją lub znakiem tabulacji.

Jeśli polecenie lub dyrektywa musi być kontynuowana w następnym wierszu, używany jest znak odwrotnego ukośnika: \.

Domyślnie język asemblerowy nie rozróżnia wielkich i małych liter podczas pisania poleceń lub dyrektyw.

Przykłady linii kodu:

Policz db 1 ; Nazwa, dyrektywa, jeden operand
ruch, 0 ; Polecenie, dwa argumenty
cbw; Komenda

Tagi

Etykieta w asemblerze może zawierać następujące znaki:

  • wszystkie litery alfabetu łacińskiego;
  • liczby od 0 do 9;
  • znaki specjalne: _, @, $,?.

Kropka może być użyta jako pierwszy znak etykiety, ale niektóre kompilatory nie zalecają używania tego znaku. Zarezerwowane nazwy asemblera (dyrektywy, operatory, nazwy poleceń) nie mogą być używane jako etykiety.

Pierwszy znak na etykiecie musi być literą lub znakiem specjalnym (ale nie cyfrą). Maksymalna długość etykiety to 31 znaków. Wszystkie etykiety, które są napisane w wierszu, który nie zawiera dyrektywy asemblera, muszą kończyć się dwukropkiem:.

Polecenia

Komenda mówi tłumaczowi, jakie działanie powinien podjąć mikroprocesor. W segmencie danych polecenie (lub dyrektywa) definiuje pole, obszar roboczy lub stałą. W segmencie kodu polecenie definiuje akcję, taką jak transfer (mov) lub dodanie (add).

Dyrektywy

Asembler posiada szereg operatorów, które pozwalają kontrolować proces składania i generowania zestawienia. Te operatory nazywają się dyrektywy ... Działają tylko w procesie asemblacji programu i w przeciwieństwie do instrukcji nie generują kodów maszynowych.

Operandy

Argument - obiekt, na którym wykonywana jest instrukcja maszynowa lub operator języka programowania.
Instrukcja może mieć jeden lub dwa operandy lub wcale. Liczba operandów jest domyślnie określona przez kod komendy.
Przykłady:

  • Brak operandów ret; Return
  • Jeden operand inc ecx; Zwiększ ecx
  • Dwa operandy dodają eax, 12; Dodaj 12 do eax

Etykieta, polecenie (dyrektywa) i operand nie muszą zaczynać się w określonej pozycji w łańcuchu. Zaleca się jednak zapisanie ich w kolumnie dla lepszej czytelności programu.

Operandy mogą być

  • identyfikatory;
  • ciągi znaków ujęte w pojedyncze lub podwójne cudzysłowy;
  • liczby całkowite w notacji binarnej, ósemkowej, dziesiętnej lub szesnastkowej.
Identyfikatory

Identyfikatory - sekwencje prawidłowych znaków używanych do oznaczania obiektów programu, takich jak kody operacji, nazwy zmiennych i nazwy etykiet.

Zasady pisania identyfikatorów.

  • Identyfikator może składać się z jednego lub kilku znaków.
  • Jako symbole mogą być użyte litery alfabetu łacińskiego, cyfry i niektóre znaki specjalne: _,?, $, @.
  • Identyfikator nie może zaczynać się od cyfry.
  • Identyfikator może mieć do 255 znaków.
  • Tłumacz akceptuje pierwsze 32 znaki identyfikatora i ignoruje resztę.
Komentarze (1)

Komentarze są oddzielone od linii wykonywalnej przez a; ... W tym przypadku wszystko, co jest napisane po symbolu średnika i do końca wiersza, jest komentarzem. Użycie komentarzy w programie poprawia jego przejrzystość, zwłaszcza tam, gdzie cel zestawu instrukcji nie jest jasny. Komentarz może zawierać dowolne znaki, które można wydrukować, w tym spację. Komentarz może obejmować cały wiersz lub podążać za poleceniem w tym samym wierszu.

Struktura programu montażowego

Program napisany w asemblerze może składać się z kilku części, zwanych moduły ... Każdy moduł może mieć zdefiniowany jeden lub więcej segmentów danych, stosu i kodu. Każdy kompletny program w języku asemblerowym musi zawierać jeden główny lub główny moduł, od którego rozpocznie się jego wykonanie. Moduł może zawierać segmenty kodu, segmenty danych i segmenty stosu, zadeklarowane przy użyciu odpowiednich dyrektyw. Przed zadeklarowaniem segmentów należy określić model pamięci za pomocą dyrektywy .MODEL.

Przykład programu asemblera „nie rób nic”:

686P
.WZÓR PŁASKI, STDCALL
.DANE
.KOD
POCZĄTEK:

GNIĆ
KONIEC START

Ten program zawiera tylko jedno polecenie mikroprocesora. To polecenie to RET. Zapewnia prawidłowe zakończenie programu. Ogólnie rzecz biorąc, to polecenie służy do wyjścia z procedury.
Pozostała część programu związana jest z pracą tłumacza.
.686P — Dozwolone polecenia trybu chronionego Pentium 6 (Pentium II). Ta dyrektywa wybiera obsługiwany zestaw instrukcji asemblera przez określenie modelu procesora. Litera P na końcu dyrektywy informuje tłumacza, że ​​procesor działa w trybie chronionym.
.MODEL FLAT, stdcall to płaski model pamięci. Ten model pamięci jest używany w systemie operacyjnym Windows. standardowe wywołanie
.DATA - segment programu zawierający dane.
.CODE - blok programu zawierający kod.
START to etykieta. W asemblerze etykiety odgrywają dużą rolę, co nie ma miejsca w nowoczesnych językach wysokiego poziomu.
KONIEC START - koniec programu i komunikat dla tłumacza o konieczności rozpoczęcia wykonywania programu od etykiety START.
Każdy moduł musi zawierać dyrektywę END, aby oznaczyć koniec kod źródłowy programy. Wszystkie wiersze następujące po dyrektywie END są ignorowane. Jeśli pominiesz dyrektywę END, generowany jest błąd.
Etykieta określona po dyrektywie END informuje tłumacza o nazwie modułu głównego, od którego rozpoczyna się wykonywanie programu. Jeżeli program zawiera jeden moduł, etykietę po dyrektywie END można pominąć.

Temat 1.4 Mnemotechnika asemblera. Struktura i formaty poleceń. Rodzaje adresowania. Zestaw poleceń mikroprocesora

Plan:

1 Język asemblera. Podstawowe koncepcje

2 Symbole języka asemblera

3 Rodzaje instrukcji asemblera

4 dyrektywy montażowe

5 Zestaw instrukcji procesora

1 jajęzyk programowania. Podstawowe koncepcje

język programowaniajest symboliczną reprezentacją języka maszynowego. Wszystkie procesy w maszynie na najniższym poziomie sprzętowym są sterowane wyłącznie poleceniami (instrukcjami) języka maszynowego. Stąd jasne jest, że pomimo ogólnej nazwy, język asemblera dla każdego typu komputera jest inny.

Program w języku asemblerowym to zbiór bloków pamięci zwanych segmenty pamięci. Program może składać się z jednego lub więcej takich segmentów bloków. Każdy segment zawiera zestaw zdań językowych, z których każdy zajmuje oddzielny wiersz kodu programu.

Zdania asemblerowe są czterech typów:

1) komendy lub instrukcje, które są symbolicznymi odpowiednikami instrukcji maszynowych. W procesie translacji instrukcje asemblera są konwertowane na odpowiednie polecenia zestawu instrukcji mikroprocesora;

2) makra -zdania tekstu programu uformowane w określony sposób, które podczas emisji są zastępowane innymi zdaniami;

3) dyrektywy,które są instrukcjami dla tłumacza asemblera, aby wykonał określone czynności. Dyrektywy nie mają analogii w reprezentacji maszynowej;

4) linie komentarza zawierające dowolne symbole, w tym litery alfabetu rosyjskiego. Komentarze są ignorowane przez tłumacza.

­ Struktura programu montażowego. Składnia zespołu.

Zdania tworzące program mogą być konstrukcją składniową odpowiadającą poleceniu, makro, dyrektywie lub komentarzowi. Aby tłumacz asemblera mógł je rozpoznać, muszą być uformowane zgodnie z pewnymi regułami składniowymi. Najlepszym sposobem na to jest użycie formalnego opisu składni języka, takiego jak reguły gramatyczne. Najczęstsze sposoby opisania takiego języka programowania - diagramy składni oraz rozszerzone formy Backus-Naur. Wygodniejszy w praktycznym użyciu diagramy składni. Na przykład składnię zdań asemblera można opisać za pomocą diagramów składni przedstawionych na poniższych rysunkach 10, 11, 12.

Rysunek 10 - Format zdania zespołu


­ Rysunek 11 - Format dyrektyw

­ Rysunek 12 - Format poleceń i makr

Na tych liczbach:

­ Nazwa etykiety- identyfikator, którego wartością jest adres pierwszego bajtu zdania tekstu źródłowego programu, który wyznacza;

­ Nazwa -identyfikator, który odróżnia tę dyrektywę od innych dyrektyw o tej samej nazwie. W wyniku przetworzenia określonej dyrektywy przez asembler, tej nazwie można przypisać pewne cechy;

­ kod operacyjny (COP) i dyrektywa - są to mnemoniczne oznaczenia odpowiedniej instrukcji maszynowej, makra lub dyrektywy translatora;

­ operandy -części polecenia, makra lub dyrektywy asemblera, które wyznaczają obiekty, którymi mają być manipulowane. Operandy asemblera są opisywane za pomocą wyrażeń ze stałymi numerycznymi i tekstowymi, etykietami i identyfikatorami zmiennych z użyciem znaków operacji i niektórych słów zastrzeżonych.

Pomoc w diagramach składni znajdź, a następnie przejdź od wejścia diagramu (po lewej) do jego wyjścia (po prawej). Jeśli taka ścieżka istnieje, to zdanie lub konstrukcja są poprawne składniowo. Jeśli nie ma takiej ścieżki, to kompilator nie zaakceptuje tej konstrukcji.

­ 2 symbole języka asemblera

Dozwolone znaki podczas pisania tekstu programu to:

1) wszystkie litery łacińskie: A-Z,a-z... W takim przypadku wielkie i małe litery są uważane za równoważne;

2) liczby od 0 przed 9 ;

3) znaki ? , @ , $ , _ , & ;

4) separatory , . () < > { } + / * % ! " " ? = # ^ .

Zdania asemblera są tworzone z tokeny, które są syntaktycznie nierozłącznymi sekwencjami poprawnych znaków języka, które mają znaczenie dla tłumacza.

leksemy są:

1) identyfikatory - sekwencje poprawnych znaków używane do oznaczania obiektów programu, takich jak kody operacji, nazwy zmiennych i nazwy etykiet. Zasada pisania identyfikatorów jest następująca: identyfikator może składać się z jednego lub więcej znaków;

2) ciągi znaków - ciągi znaków ujęte w pojedyncze lub podwójne cudzysłowy;

3) liczby całkowite jednego z następujących systemów liczbowych : binarny, dziesiętny, szesnastkowy. Identyfikacja liczb podczas pisania ich w programach asemblerowych odbywa się zgodnie z pewnymi zasadami:

4) liczby dziesiętne nie wymagają dodatkowych symboli do ich identyfikacji, np. 25 lub 139. Do identyfikacji w kodzie źródłowym programu liczby binarne po napisaniu zer i jedynek wchodzących w ich skład należy wstawić łacinę „ b”, Na przykład 10010101 b.

5) Liczby szesnastkowe mają więcej konwencji, gdy są zapisywane:

Po pierwsze składają się z liczb 0...9 , małe i wielkie litery alfabetu łacińskiego a,b, C,D,mi,F lub A,b,C,D,mi,F.

Po drugie, tłumacz może mieć trudności z rozpoznaniem liczb szesnastkowych ze względu na to, że mogą one składać się albo z samych cyfr 0…9 (np. 190845), albo zaczynać się od litery alfabetu łacińskiego (np. ef15). Aby "wyjaśnić" tłumaczowi, że dany token nie jest liczbą dziesiętną ani identyfikatorem, programista musi w specjalny sposób wybrać liczbę szesnastkową. Aby to zrobić, na końcu sekwencji cyfr szesnastkowych, które tworzą liczbę szesnastkową, napisz łacińską literę „ h”. to wymagany warunek... Jeśli liczba szesnastkowa zaczyna się od litery, przed nią zapisywane jest wiodące zero: 0 ef15 h.

Niemal każde zdanie zawiera opis przedmiotu, na którym lub za pomocą którego wykonywane jest jakieś działanie. Obiekty te nazywają się operandy... Można je zdefiniować w następujący sposób: operandy- są to obiekty (niektóre wartości, rejestry lub komórki pamięci), na które działają instrukcje lub dyrektywy, lub są to obiekty definiujące lub wyjaśniające działanie instrukcji lub dyrektyw.

Możliwe jest przeprowadzenie następującej klasyfikacji argumentów:

­ operandy stałe lub natychmiastowe;

­ operandy adresowe;

­ ruchome operandy;

licznik adresów;

­ operand rejestru;

­ argumenty bazowe i indeksowe;

­ operandy strukturalne;

dokumentacja.

Argumenty to elementarne komponenty, z których powstaje część instrukcji maszynowej, oznaczająca obiekty, na których wykonywana jest operacja. W bardziej ogólnym przypadku operandy mogą być zawarte jako składniki w bardziej złożonych formacjach, zwanych wyrażenia.

Wyrażenia to kombinacje operandów i operatorów, traktowane jako całość. Wynikiem oceny wyrażenia może być adres jakiejś komórki pamięci lub pewna stała (bezwzględna) wartość.

­ 3 Rodzaje instrukcji asemblera

Wymieńmy możliwe typy operatorzy asemblera oraz syntaktyczne zasady tworzenia wyrażeń asemblera:

­ operatory arytmetyczne;

­ operatorzy zmian;

­ operatory porównania;

­ operatory logiczne;

­ operator indeksu;

­ operator nadpisania typu;

­ operator redefinicji segmentu;

­ operator nazewnictwa typu struktury;

­ operator do uzyskania składnika segmentu adresu wyrażenia;

­ operator, aby uzyskać przesunięcie wyrażenia.

1 Dyrektywy asemblera

­ Dyrektywy asemblera to:

1) Dyrektywy segmentacyjne. W trakcie poprzedniej dyskusji poznaliśmy wszystkie podstawowe zasady pisania poleceń i operandów w programie asemblera. Otwarte pozostaje pytanie, jak poprawnie sformułować sekwencję poleceń, aby tłumacz mógł je przetworzyć, a mikroprocesor mógł wykonać.

Rozważając architekturę mikroprocesora dowiedzieliśmy się, że posiada on sześć rejestrów segmentowych, dzięki którym może pracować jednocześnie:

­ z jednym segmentem kodu;

­ z jednym segmentem stosu;

­ z jednym segmentem danych;

­ z trzema dodatkowymi segmentami danych.

Fizycznie segment jest obszarem pamięci zajmowanym przez instrukcje i (lub) dane, których adresy są obliczane względem wartości w odpowiednim rejestrze segmentowym. Opisem składniowym segmentu w asemblerze jest konstrukcja pokazana na rysunku 13:


­ Rysunek 13 - Syntaktyczny opis segmentu w asemblerze

Należy zauważyć, że funkcjonalność segmentu jest nieco szersza niż po prostu dzielenie programu na bloki kodu, danych i stosu. Segmentacja jest częścią more wspólny mechanizm związany z koncepcja programowania modułowego. Zakłada ujednolicenie konstrukcji modułów obiektowych tworzonych przez kompilator, w tym pochodzących z różnych języków programowania. Pozwala to na łączenie programów napisanych w różnych językach. Operandy w dyrektywie SEGMENT mają na celu implementację różnych wariantów takiej unii.

2) Wykaz dyrektyw zarządzania. Dyrektywy sterujące listowaniem są podzielone na następujące grupy:

­ ogólne dyrektywy sterujące listowaniem;

­ dyrektywy do wyprowadzania na listę dołączanych plików;

­ dyrektywy do wyprowadzania warunkowych bloków asemblera;

­ dyrektywy do listowania makr;

­ dyrektywy do wyprowadzania informacji o odsyłaczach do listingu;

­ dyrektywy dotyczące zmiany formatu aukcji.

2 Zestaw instrukcji procesora

Zestaw instrukcji procesora pokazano na rysunku 14.

Rozważmy główne grupy poleceń.

­ Rysunek 14 - Klasyfikacja instrukcji asemblera

Zespoły to:

1 Polecenia przesyłania danych. Te polecenia zajmują bardzo ważne miejsce w zestawie instrukcji dowolnego procesora. Pełnią następujące podstawowe funkcje:

­ przechowywanie zawartości wewnętrznych rejestrów procesora w pamięci;

­ kopiowanie treści z jednego obszaru pamięci do drugiego;

­ zapis do urządzeń I/O i odczyt z urządzeń I/O.

Na niektórych procesorach wszystkie te funkcje są wykonywane przez jedno polecenie. MOV (dla transferów bajtów - MOVB ) ale z różnymi metodami adresowania operandów.

Na innych procesorach oprócz polecenia MOV istnieje kilka innych poleceń do wykonywania wymienionych funkcji. Również polecenia przesyłania danych obejmują polecenia wymiany informacji (ich oznaczenie oparte jest na słowie Giełda ). Wymiana informacji między rejestrami wewnętrznymi, między dwiema połówkami jednego rejestru ( ZAMIENIAĆ ) lub między rejestrem a komórką pamięci.

2 Polecenia arytmetyczne... Instrukcje arytmetyczne traktują kody operandów jako numeryczne kody binarne lub BCD. Polecenia te można podzielić na pięć głównych grup:

­ polecenia operacji na punktach stałych (dodawanie, odejmowanie, mnożenie, dzielenie);

­ polecenia zmiennoprzecinkowe (dodawanie, odejmowanie, mnożenie, dzielenie);

­ polecenia czyszczenia;

­ polecenia inkrementacji i dekrementacji;

­ polecenie porównania.

3 Komendy operacji ze stałym punktem pracują z kodami w rejestrach procesora lub w pamięci jak przy zwykłych kodach binarnych. Instrukcje zmiennoprzecinkowe (przecinkowe) używają formatu przedstawiania liczb z porządkiem i mantysą (zwykle te liczby zajmują dwie kolejne komórki pamięci). W nowoczesnym potężne procesory zbiór instrukcji zmiennoprzecinkowych nie ogranicza się tylko do czterech operacji arytmetycznych, ale zawiera również wiele innych, bardziej złożonych instrukcji, na przykład obliczanie funkcji trygonometrycznych, funkcji logarytmicznych, a także złożonych funkcji niezbędnych do przetwarzania dźwięku i obrazów.

4 Instrukcje kasujące mają na celu zapisanie kodu zerowego do rejestru lub komórki pamięci. Te polecenia mogą być nadpisane przy zerowych poleceniach transferu, ale zespoły specjalne czyszczenie jest zwykle szybsze niż przekazywanie poleceń.

5 poleceń zwiększania (zwiększania o jeden) i zmniejszania

(zmniejszenia o jeden) są również bardzo wygodne. W zasadzie można je zastąpić poleceniami dodawania z jednym lub odejmowania jednego, ale inkrementacja i dekrementacja są szybsze niż dodawanie i odejmowanie. Instrukcje te wymagają jednego operandu wejściowego, który jest również operandem wyjściowym.

6 Instrukcja porównania porównuje dwa argumenty wejściowe. W rzeczywistości oblicza różnicę między tymi dwoma operandami, ale nie tworzy operandu wyjściowego, a jedynie zmienia bity w rejestrze stanu procesora na podstawie wyniku tego odejmowania. Kolejna instrukcja następująca po instrukcji porównania (zwykle instrukcja rozgałęzienia) przeanalizuje bity w rejestrze stanu procesora i wykona akcje w zależności od ich wartości. Niektóre procesory udostępniają instrukcje łączenia łańcuchowego dwóch sekwencji operandów w pamięci.

7 Polecenia logiczne. Instrukcje logiczne wykonują logiczne (bitowe) operacje na operandach, to znaczy traktują kody operandów nie jako pojedynczą liczbę, ale jako zestaw oddzielnych bitów. Tym różnią się od poleceń arytmetycznych. Polecenia logiczne wykonują następujące podstawowe operacje:

­ logiczne AND, logiczne OR, dodawanie modulo 2 (Exclusive OR);

­ przesunięcia logiczne, arytmetyczne i cykliczne;

­ sprawdzanie bitów i operandów;

­ ustawianie i kasowanie bitów (flag) rejestru stanu procesora ( PSW).

Instrukcje logiczne pozwalają na obliczenie podstawowych funkcji logicznych z dwóch operandów wejściowych bit po bicie. Ponadto operacja AND służy do wymuszenia wyczyszczenia określonych bitów (jako jeden z operandów używany jest kod maski, w którym bity do wyczyszczenia są ustawione na zero). Operacja OR służy do wymuszonego ustawienia określonych bitów (jako jeden z operandów stosuje się kod maski, w którym bity wymagające ustawienia jedynki są równe jedynce). Operacja „Exclusive OR” służy do odwracania określonych bitów (kod maski jest używany jako jeden z operandów, w którym bity do odwrócenia są ustawione na jeden). Instrukcje wymagają dwóch operandów wejściowych i tworzą jeden operand wyjściowy.

8 Polecenia Shift pozwalają przesuwać kod operandu bit po bicie w prawo (w kierunku bitów mniej znaczących) lub w lewo (w kierunku bitów wyższych). Rodzaj przesunięcia (logiczne, arytmetyczne lub cykliczne) określa, jaka będzie nowa wartość najbardziej znaczącego bitu (przy przesunięciu w prawo) lub najmniej znaczącego bitu (przy przesunięciu w lewo), a także określa, czy poprzednia wartość najbardziej znaczącego bitu (przy przesunięciu w lewo) zostanie gdzieś zapisany lub najmniej znaczący bit (przy przesunięciu w prawo). Przesunięcia cykliczne umożliwiają przesuwanie bitów operandu w sposób kołowy (zgodnie z ruchem wskazówek zegara przy przesunięciu w prawo lub przeciwnie do ruchu wskazówek zegara przy przesunięciu w lewo). W tym przypadku flaga przeniesienia może, ale nie musi być zawarta w pierścieniu zmiany biegów. Bit flagi przeniesienia (jeśli jest używany) przechowuje wartość najbardziej znaczącego bitu przy przesunięciu w lewo i najmniej znaczącego bitu przy przesunięciu w prawo. Odpowiednio, wartość bitu flagi przeniesienia zostanie nadpisana w najmniej znaczącym bicie podczas jazdy w lewo iw najbardziej znaczącym bicie podczas jazdy w prawo.

9 Polecenia przejść. Instrukcje skoku są zaprojektowane do organizowania wszelkiego rodzaju pętli, rozgałęzień, wywołań podprogramów itp., to znaczy zakłócają sekwencyjny przepływ programu. Polecenia te zapisują nową wartość do rejestru licznika poleceń i w ten sposób powodują, że procesor przeskakuje nie do następnego polecenia w kolejności, ale do dowolnego innego polecenia w pamięci programu. Niektóre polecenia przejścia zapewniają dalszy powrót z powrotem do punktu, z którego dokonano przejścia, inne tego nie zapewniają. Jeśli podano return, to bieżące parametry procesora są zapisywane na stosie. Jeśli nie zostanie podany zwrot, bieżące parametry procesora nie zostaną zapisane.

Polecenia przejścia bez cofania dzielą się na dwie grupy:

­ bezwarunkowe polecenia skoku;

­ polecenia skoku warunkowego.

Te polecenia używają słów Gałąź i skacz.

Instrukcje skoku bezwarunkowego powodują skok do nowy adres nieważne co. Mogą spowodować przejście do określona wartość przesunięcia (do przodu lub do tyłu) lub do określonego adresu pamięci. Wartość przesunięcia lub nowa wartość adresu jest określona jako argument wejściowy.

Instrukcje skoku warunkowego nie zawsze powodują skok, ale tylko wtedy, gdy spełnione są określone warunki. Warunki te są zwykle wartościami flag w rejestrze stanu procesora ( PSW ). Oznacza to, że warunek przejścia jest wynikiem poprzedniej operacji, która zmienia wartości flag. W sumie takich warunków skoku może być od 4 do 16. Kilka przykładów poleceń skoku warunkowego:

­ przejście, jeśli jest równe zero;

­ przejście, jeśli nie jest równe zero;

­ skacz, jeśli jest przepełnienie;

­ skacz, jeśli nie ma przelewu;

­ przejście, jeśli jest większe od zera;

­ skok, jeśli jest mniejszy lub równy zero.

Jeśli warunek przejścia jest spełniony, nowa wartość jest ładowana do rejestru poleceń. Jeśli warunek skoku nie jest spełniony, licznik instrukcji jest po prostu zwiększany, a procesor wybiera i wykonuje następną instrukcję w kolejności.

Polecenie porównania (CMP) poprzedzające polecenie rozgałęzienia warunkowego (lub nawet kilka poleceń rozgałęzienia warunkowego) jest używane specjalnie do sprawdzania warunków skoku. Ale flagi można ustawić dowolnym innym poleceniem, na przykład poleceniem przesyłania danych, dowolnym poleceniem arytmetycznym lub logicznym. Zwróć uwagę, że same polecenia skoku nie zmieniają flag, co pozwala po prostu umieścić kilka poleceń skoku jeden po drugim.

Polecenia przerwań zajmują szczególne miejsce wśród poleceń skoku wstecz. Instrukcje te wymagają numeru przerwania (adresu wektora) jako argumentu wejściowego.

Wyjście:

Asembler jest symboliczną reprezentacją języka maszynowego. Język asemblera dla każdego typu komputera jest inny. Program w języku asemblerowym jest zbiorem bloków pamięci zwanych segmentami pamięci. Każdy segment zawiera zestaw zdań językowych, z których każdy zajmuje oddzielny wiersz kodu programu. Zdania asemblerowe są czterech typów: polecenia lub instrukcje, makra, dyrektywy, wiersze komentarza.

Wszystkie litery łacińskie są prawidłowymi znakami podczas pisania tekstu programu: A-Z,a-z... W takim przypadku wielkie i małe litery są uważane za równoważne; liczby z 0 przed 9 ; oznaki ? , @ , $ , _ , & ; separatory , . () < > { } + / * % ! " " ? = # ^ .

Stosuje się następujące typy instrukcji asemblera i reguły składniowe do tworzenia wyrażeń asemblera. operatory arytmetyczne, operatory przesunięcia, operatory porównania, operatory logiczne, operator indeksu, operator przesłaniania typu, operator przesłaniania segmentu, operator nazewnictwa typu struktury, operator do pobierania składnika segmentu adresu wyrażenia, operator do pobierania przesunięcia wyrażenia.

System dowodzenia podzielony jest na 8 głównych grup.

­ Pytania kontrolne:

1 Czym jest język asemblera?

2 Jakie symbole mogą być użyte do pisania poleceń w asemblerze?

3 Czym są etykiety i ich przeznaczenie?

4 Wyjaśnij strukturę poleceń asemblera.

5 Wymień 4 typy zdań asemblera.

1. Architektura PC ………………………………………………………… 5

    1.1. Rejestry.

    1.1.1 Rejestry ogólny cel.

1.1.2. Rejestry segmentowe

1.1.3 Rejestr flag

1.2. Organizacja pamięci.

1.3. Prezentacja danych.

1.3.1 Typy danych

1.3.2 Reprezentacja znaków i ciągów

2. Operatorzy programu asemblera ……………………………………

    1. Polecenia języka asemblera

2.2. Tryby adresowania i formaty instrukcji maszyny

3. Pseudooperatorzy ……………………………………………………….

3.1 Dyrektywy dotyczące definicji danych

3.2 Struktura programu asemblerowego

3.2.1 Segmenty programu. Przyjmij dyrektywę

3.2.3 Uproszczona dyrektywa segmentacji

4. Składanie i podpinanie programu ………………………….

5. Komendy do wysyłania danych …………………………………………….

    5.1 Polecenia ogólne

    5.2 Polecenia do pracy ze stosem

5.3 Polecenia we/wy

5.4 Polecenia przekazywania adresu

5.5 Komendy do przesyłania flag

6. Polecenia arytmetyczne ……………………………………………….

    6.1 Operacje arytmetyczne na binarnych liczbach całkowitych

6.1.1 Dodawanie i odejmowanie

6.1.2 Polecenia inkrementacji i dekrementacji odbiornika o jeden

6.2 Mnożenie i dzielenie

6.3 Zmiana znaku

7. Operacje logiczne ………………………………………………….

8. Zmiany i zmiany cykliczne …………………………………………

9. Operacje na ciągach ………………………………………………….

10. Logika i organizacja programów ………………………………………

10.1 Bezwarunkowe skoki

10.2 Skoki warunkowe

10.4 Procedury w asemblerze

10.5 Przerwania INT

10.6 Oprogramowanie systemowe

10.6.1.1 Odczytywanie klawiatury.

10.6.1.2 Wyświetlanie znaków na ekranie

10.6.1.3 Koniec programów.

10.6.2.1 Wybór trybów wyświetlania

11. Pamięć dyskowa ……………………………………………………… ..

11.2 Tabela alokacji plików

11.3 Dysk we/wy

11.3.1 Zapisywanie pliku na dysku

11.3.1.1 Dane w formacie ASCIIZ

11.3.1.2 Numer akt

11.3.1.3 Utwórz plik na dysku

11.3.2 Czytanie pliku z dysku

Wstęp

Asembler jest symboliczną reprezentacją języka maszynowego. Wszystkie procesy w komputerze osobistym (PC) na najniższym poziomie sprzętowym są sterowane wyłącznie poleceniami (instrukcjami) języka maszynowego. Niemożliwe jest prawdziwe rozwiązanie problemów związanych ze sprzętem (lub nawet problemów zależnych od sprzętu, takich jak poprawa wydajności programu) bez znajomości asemblera.

Asembler jest wygodną formą poleceń bezpośrednio dla komponentów PC i wymaga znajomości właściwości i możliwości układu scalonego zawierającego te komponenty, czyli mikroprocesora PC. Tak więc język asemblera jest bezpośrednio związany z wewnętrzną organizacją PC. I nie jest przypadkiem, że prawie wszystkie kompilatory języków wysokiego poziomu obsługują dostęp do poziomu programowania w języku asemblerowym.

Elementem szkolenia profesjonalnego programisty jest koniecznie nauka asemblera. Dzieje się tak dlatego, że programowanie w języku asemblerowym wymaga znajomości architektury PC, co pozwala na tworzenie wydajniejszych programów w innych językach i łączenie ich z programami w języku asemblerowym.

Podręcznik zajmuje się zagadnieniami programowania w języku asemblera dla komputerów opartych na mikroprocesorach firmy Intel.

Ten samouczek jest skierowany do wszystkich zainteresowanych architekturą procesora i podstawami programowania w języku asemblerowym, przede wszystkim programistów.

    Architektura PC.

Architektura komputera to abstrakcyjna reprezentacja komputera, która odzwierciedla jego strukturę, obwody i organizację logiczną.

Wszystkie współczesne komputery mają pewne wspólne i indywidualne właściwości architektury. Poszczególne właściwości są nierozerwalnie związane tylko z określonym modelem komputera.

Pojęcie architektury komputerowej obejmuje:

    schemat blokowy komputera;

    środki i metody dostępu do elementów, schemat strukturalny KOMPUTER;

    zestaw i dostępność rejestrów;

    organizacja i metody adresowania;

    sposób prezentacji i format danych komputerowych;

    zestaw instrukcji do komputera;

    formaty instrukcji maszynowych;

    obsługa przerwań.

Główne elementy sprzętu komputerowego: jednostka systemowa, klawiatura, urządzenia wyświetlające, napędy dysków, urządzenia drukujące (drukarka) oraz różne urządzenia komunikacyjne. Jednostka systemowa składa się z płyty głównej, zasilacza i gniazd rozszerzeń na dodatkowe karty. Płyta systemowa zawiera mikroprocesor, pamięć tylko do odczytu (ROM), Baran(RAM) i koprocesor.

      Rejestry.

Wewnątrz mikroprocesora informacje zawarte są w grupie 32 rejestrów (16 użytkowników, 16 systemowych), w pewnym stopniu dostępnych dla programisty. Ponieważ samouczek poświęcony jest programowaniu dla mikroprocesora 8088-i486, najbardziej logiczne jest rozpoczęcie tego tematu od omówienia dostępnych dla użytkownika rejestrów wewnętrznych mikroprocesora.

Rejestry użytkownika są używane przez programistę do pisania programów. Rejestry te obejmują:

    osiem rejestrów 32-bitowych (rejestry ogólnego przeznaczenia) EAX/AX/AH/AL, EBX/BX/BH/BL, ECX/CX/CH/CL, EDX/DX/DLH/DL, EBP/BP, ESI/SI, EDI/DI, ESP/SP;

    sześć 16-bitowych rejestrów segmentowych: CS, DS, SS, ES, FS, GS;

    rejestry statusowe i kontrolne: rejestr flag EFLAGS / FLAGS oraz rejestr wskaźników instrukcji EIP / IP.

Ukośnik oznacza części jednego rejestru 32-bitowego. Przedrostek E (Extended) oznacza użycie rejestru 32-bitowego. Do pracy z bajtami używane są rejestry z przedrostkami L (niski) i H (wysoki), na przykład AL, CH - oznaczające niskie i wysokie bajty 16-bitowych części rejestrów.

        Rejestry ogólnego przeznaczenia.

EAX / AX / AH / AL (rejestr akumulatorowy) - bateria... Używany w mnożeniu i dzieleniu, w operacjach I/O oraz w niektórych operacjach na ciągach.

EBX / BX / BH / BL - rejestr bazowy(rejestr bazowy), często używany przy adresowaniu danych w pamięci.

ECX / CX / CH / CL - licznik(rejestr liczników), używany jako licznik powtórzeń pętli.

EDX / DX / DH / DL - rejestr danych(rejestr danych), używany do przechowywania danych pośrednich. Jest to obowiązkowe w niektórych poleceniach.

Wszystkie rejestry w tej grupie umożliwiają dostęp do ich „niższych” części. Tylko dolne 16- i 8-bitowe części tych rejestrów mogą być używane do samodzielnego adresowania. Górne 16 bitów tych rejestrów nie jest dostępnych jako niezależne obiekty.

Aby obsługiwać polecenia przetwarzania linii, które umożliwiają sekwencyjne przetwarzanie łańcuchów elementów o długości 32, 16 lub 8 bitów, użyj:

ESI / SI (rejestr indeksów źródłowych) - indeks źródło... Zawiera adres bieżącego elementu źródłowego.

EDI / DI (rejestr indeksów dystynkcji) - indeks odbiorca(odbiorca). Zawiera bieżący adres w ciągu odbiornika.

W architekturze mikroprocesora struktura danych - stos - jest obsługiwana na poziomie sprzętowo-programowym. Istnieją specjalne polecenia i specjalne rejestry do pracy ze stosem. Należy zauważyć, że stos jest zapełniony w kierunku mniejszych adresów.

ESP / SP (rejestr wskaźnika stosu) - Zarejestruj się wskaźnik stos... Zawiera wskaźnik do szczytu stosu w bieżącym segmencie stosu.

EBP / BP (rejestr wskaźnika bazowego) - rejestr wskaźnika bazowego stosu... Zaprojektowany do organizowania losowego dostępu do danych wewnątrz stosu.

1.1.2. Rejestry segmentowe

W modelu oprogramowania mikroprocesora jest sześć rejestry segmentowe: CS, SS, DS, ES, GS, FS. Ich istnienie wynika ze specyfiki organizacji i wykorzystania pamięci RAM przez mikroprocesory Intela. Sprzęt mikroprocesorowy wspiera strukturalną organizację programu składającą się z: segmenty. Aby wskazać segmenty dostępne w ten moment rejestry segmentowe są przeznaczone. Mikroprocesor obsługuje następujące typy segmentów:

    Segment kodu. Zawiera polecenia programu. Aby uzyskać dostęp do tego segmentu, użyj rejestru CS (rejestr segmentu kodu) - rejestr kodu segmentu... Zawiera adres segmentu instrukcji maszynowych, do którego mikroprocesor ma dostęp.

    Segment danych. Zawiera dane przetwarzane przez program. Aby uzyskać dostęp do tego segmentu, użyj rejestru DS (rejestr segmentu danych) - segmentowy rejestr danych który przechowuje adres segmentu danych bieżącego programu.

    Segment stosu. Ten segment reprezentuje obszar pamięci zwany stosem. Mikroprocesor organizuje stos zgodnie z zasadą – kto pierwszy, ten pierwszy. Rejestr SS (rejestr segmentu stosu) służy do uzyskiwania dostępu do stosu - rejestr segmentów stosu zawierający adres segmentu stosu.

    Dodatkowy segment danych. Przetworzone dane mogą znajdować się w trzech dodatkowych segmentach danych. Domyślnie zakłada się, że dane znajdują się w segmencie danych. W przypadku korzystania z dodatkowych segmentów danych, ich adresy muszą być wyraźnie określone za pomocą specjalnych przedrostków zastępujących segmenty w poleceniu. Adresy dodatkowych segmentów danych muszą być zawarte w rejestrach ES, GS, FS (rozszerzenie rejestrów segmentu danych).

        Rejestry kontrolne i statusowe

Mikroprocesor zawiera kilka rejestrów zawierających informacje o stanie zarówno samego mikroprocesora, jak i programu, którego polecenia są aktualnie ładowane do potoku. Ono:

Rejestr wskaźnika poleceń EIP / IP;

    flagi rejestru EFLAGI / FLAGI.

Korzystając z tych rejestrów można uzyskać informacje o wynikach wykonania polecenia oraz wpływać na stan samego mikroprocesora.

EIP/IP (rejestr instrukcji) - wskaźnik zespoły... Rejestr EIP/IP ma szerokość 32 lub 16 bitów i zawiera przesunięcie następnej instrukcji do wykonania względem zawartości rejestru segmentu CS w bieżącym segmencie instrukcji. Rejestr ten nie jest bezpośrednio dostępny, ale można go zmienić za pomocą poleceń skoku.

EFLAGI / FLAGI (Rejestr flag) - Zarejestruj się flagi... Głębokość bitowa 32/16. Poszczególne bity tego rejestru mają określony cel funkcjonalny i nazywane są flagami. Flaga to bit, który przyjmuje wartość 1 („flaga jest ustawiona”), jeśli spełniony jest określony warunek, a wartość 0 („flaga jest wyczyszczona”) w przeciwnym razie. Dolna część tego rejestru jest całkowicie analogiczna do rejestru FLAGS dla i8086.

1.1.3 Rejestr flag

Rejestr flag jest 32-bitowy i ma nazwę EFLAGS (rysunek 1). Poszczególne bity rejestru mają określony cel funkcjonalny i nazywane są flagami. Każdemu z nich przypisana jest określona nazwa (ZF, CF itp.). Mniejsze 16 bitów EFLAGS reprezentuje 16-bitowy rejestr FLAGS używany podczas wykonywania programów napisanych dla mikroprocesorów i086 i i286.

Rys. 1 Rejestr flag

Niektóre flagi są powszechnie nazywane flagami warunków; automatycznie zmieniają się, gdy polecenia są wykonywane i poprawiają pewne właściwości ich wyniku (na przykład, czy jest równe zero). Inne flagi nazywane są flagami państwowymi; zmieniają się z programu i wpływają na dalsze zachowanie procesora (na przykład przerwania blokowe).

Flagi stanu:

CF (flaga przenoszenia) - nosić flagę... Przyjmuje wartość 1, jeśli podczas dodawania liczb całkowitych pojawiła się jednostka dzielenia wyrazów, która nie „pasowała” do siatki bitowej lub jeśli podczas odejmowania liczb bez znaku pierwsza z nich była mniejsza od drugiej. W poleceniach przesunięcia bit, który wyszedł poza siatkę bitów, jest ustawiany w CF. CF przechwytuje również cechy polecenia mnożenia.

OF (flaga przepełnienia) - flaga przepełnienia... Jest ustawiony na 1, jeśli podczas dodawania lub odejmowania liczb całkowitych ze znakiem, wynik jest wynikiem, który jest większy w wartości bezwzględnej niż wartość dopuszczalna (mantysa przepełniła się i "wspięła się" na bit znaku).

ZF (flaga zero) - zero flag... Jest ustawiony na 1, jeśli wynik polecenia był równy 0.

SF (flaga znaku) - flaga znak... Jest ustawiony na 1, jeśli operacja na liczbach ze znakiem daje wynik negatywny.

PF (flaga parzystości) - flaga parytet... Równe 1, jeśli wynik następnego polecenia zawiera parzystą liczbę jedynek binarnych. Zwykle jest brany pod uwagę tylko dla operacji we/wy.

AF (pomocnicza flaga przenoszenia) - dodatkowa flaga noszenia... Naprawia specyfikę wykonywania operacji na liczbach binarno-dziesiętnych.

Flagi stanu:

DF (flaga kierunku) - flaga kierunku... Ustawia kierunek przeglądania linii w poleceniach napisowych: przy DF = 0 linie są skanowane "do przodu" (od początku do końca), przy DF = 1 - w przeciwnym kierunku.

IOPL (poziom uprawnień wejścia / wyjścia) - Poziom uprawnień we/wy. Jest używany w trybie chronionym mikroprocesora do kontroli dostępu do poleceń I/O, w zależności od uprawnień zadania.

NT (zagnieżdżone zadanie) - flaga zagnieżdżania zadań. Jest używany w trybie chronionym mikroprocesora do rejestrowania faktu, że jedno zadanie jest zagnieżdżone w innym.

Flaga systemu:

IF (flaga przerwania) - flaga przerwania... Jeśli IF = 0, procesor przestaje odpowiadać na przychodzące przerwania, jeśli IF = 1, blokada przerwań jest zwalniana.

TF (flaga pułapki) - flaga śledzenia... Jeśli TF = 1, po wykonaniu każdej instrukcji, procesor wykonuje przerwanie (o numerze 1), które może być użyte podczas debugowania programu do jego śledzenia.

RF (flaga wznowienia) - flaga wznowienia... Używane podczas obsługi przerwań z rejestrów debugowania.

VM (tryb wirtualny 8086) - wirtualna flaga 8086. 1-procesor działa w trybie wirtualnym 8086.0- procesor działa w trybie rzeczywistym lub chronionym.

AC (sprawdzenie wyrównania) - flaga kontroli wyrównania. Zaprojektowany, aby umożliwić kontrolę wyrównania podczas dostępu do pamięci.

      Organizacja pamięci.

Pamięć fizyczna, do której mikroprocesor ma dostęp, nazywa się BARAN ( lub pamięć o dostępie swobodnym - BARAN). RAM to łańcuch bajtów, które mają swój unikalny adres (jego numer), zwany fizyczny. Zakres wartości dla adresów fizycznych wynosi od 0 do 4 GB. Mechanizm zarządzania pamięcią jest całkowicie sprzętowy.

Sprzęt mikroprocesorowy obsługuje kilka modeli wykorzystania pamięci RAM:

    model segmentowy... W tym modelu pamięć dla programów jest podzielona na ciągłe obszary pamięci (segmenty), a sam program ma dostęp tylko do danych znajdujących się w tych segmentach;

    model strony... W tym przypadku pamięć RAM jest traktowana jako zestaw bloków o stałym rozmiarze 4 KB. Główne zastosowanie tego modelu wiąże się z organizacją pamięci wirtualnej, która pozwala programom na wykorzystanie przestrzeni pamięci większej niż jej ilość Pamięć fizyczna... W przypadku mikroprocesora Pentium możliwa pamięć wirtualna może wynosić do 4 TB.

Zastosowanie i implementacja tych modeli zależy od trybu pracy mikroprocesora:

    Tryb adresu rzeczywistego (tryb rzeczywisty). Tryb jest podobny do działania procesora i8086. Jest niezbędny do funkcjonowania programów opracowanych dla wczesnych modeli procesorów.

    Tryb obronny. W trybie chronionym możliwa staje się wielozadaniowość przetwarzanie informacji, ochrona pamięci za pomocą czteropoziomowego mechanizmu uprawnień i jej stronicowania.

    Tryb wirtualny 8086. W tym trybie możliwe jest uruchomienie kilku programów dla i8086. W takim przypadku możliwe jest działanie programów w trybie rzeczywistym.

Segmentacja to mechanizm adresowania, który umożliwia istnienie wielu niezależnych przestrzeni adresowych. Segment to niezależny, wspierany sprzętowo blok pamięci.

Każdy program w ogólnym przypadku może składać się z dowolnej liczby segmentów, ale ma bezpośredni dostęp do trzech głównych: kodu, danych i stosu - oraz od jednego do trzech dodatkowych segmentów danych. System operacyjny umieszcza segmenty programu w pamięci RAM pod określonymi adresami fizycznymi, a następnie umieszcza wartości tych adresów w odpowiednich rejestrach. W obrębie segmentu program uzyskuje dostęp do adresów względem początku segmentu liniowo, czyli zaczynając od adresu 0 i kończąc na adresie równym rozmiarowi segmentu. Adres względny lub stronniczość, którego mikroprocesor używa do uzyskania dostępu do danych w segmencie nazywa się efektywny.

Tworzenie adresu fizycznego w trybie rzeczywistym

W trybie rzeczywistym zakres zmiany adresu fizycznego wynosi od 0 do 1 MB. Maksymalny rozmiar segmentu to 64 KB. Odnosząc się do konkretnego adres fizyczny Pamięć RAM jest określana przez adres początku segmentu i przesunięcie w obrębie segmentu. Adres początkowy segmentu jest pobierany z odpowiedniego rejestru segmentowego. W tym przypadku rejestr segmentowy zawiera tylko 16 górnych bitów adresu fizycznego początku segmentu. Brakujące cztery najmniej znaczące bity adresu 20-bitowego są uzyskiwane przez przesunięcie wartości rejestru segmentowego w lewo o 4 bity. Operacja zmiany wykonywana jest sprzętowo. Wynikowa wartość 20-bitowa jest rzeczywistym adresem fizycznym odpowiadającym początkowi segmentu. To jest adres fizyczny jest określony jako para: segment: offset, gdzie segment to pierwsze 16 bitów adresu początkowego segmentu pamięci, do którego należy komórka, a offset to 16-bitowy adres tej komórki, liczony od początku tej pamięci segment (wartość 16 * segment + offset daje bezwzględny adres komórki). Jeżeli np. rejestr CS przechowuje wartość 1234h, to para adresów 1234h:507h określa adres bezwzględny równy 16*1234h+507h=12340h+507h=12847h. Taka para jest zapisywana w formie podwójnego słowa i (jak w przypadku liczb) w formie „odwróconej”: pierwsze słowo zawiera przesunięcie, a drugie segment, a każde z tych słów po kolei jest prezentowane w postaci forma „odwrócona”. Na przykład para 1234h:5678h zostanie zapisana tak: | 78 | 56 | 34 | 12 |.

Ten mechanizm tworzenia adresu fizycznego pozwala na relokację oprogramowania, to znaczy nie zależy od konkretnych adresów jego ładowania w pamięci RAM.

Konstrukcje asemblera

Tablice, które rozważaliśmy powyżej, to zbiór elementów tego samego typu. Ale często w aplikacjach konieczne staje się uwzględnienie pewnego zestawu danych. różne rodzaje jako jakiś pojedynczy typ.

Jest to bardzo ważne np. dla programów bazodanowych, gdzie konieczne jest powiązanie kolekcji danych różnego typu z jednym obiektem.

Na przykład wcześniej przyjrzeliśmy się Listingowi 4, w którym pracowaliśmy z tablicą elementów trzybajtowych. Każdy element z kolei reprezentował dwa elementy różnego typu: jednobajtowe pole licznika i dwubajtowe pole, które może zawierać inne informacje niezbędne do przechowywania i przetwarzania. Jeśli czytelnik zna jeden z języków wysokiego poziomu, to wie, że taki obiekt jest zwykle opisywany za pomocą specjalnego typu danych - Struktury.

W celu poprawy użyteczności języka asemblerowego wprowadzono do niego również ten typ danych.

A-priorytet Struktura to typ danych składający się ze stałej liczby elementów różnych typów.

Aby użyć struktur w programie, musisz wykonać trzy kroki:

    Zapytać się szablon struktury .

    Z definicji oznacza to zdefiniowanie nowego typu danych, który później można wykorzystać do zdefiniowania zmiennych tego typu.

    Definiować instancja struktury .

    Ten etap implikuje inicjalizację określonej zmiennej z predefiniowaną (przy użyciu szablonu) strukturą.

    Zorganizować dostęp do elementów konstrukcji .

Bardzo ważne jest, aby od samego początku zrozumieć, jaka jest różnica między opis struktura w programie i jej definiowanie.

Opisać struktura w programie oznacza jedynie wskazanie jej schematu lub szablonu; żadna pamięć nie jest przydzielona.

Ten szablon może być traktowany tylko jako informacja dla tłumacza o lokalizacji pól i ich domyślnych wartościach.

Definiować struktura oznacza poinstruowanie tłumacza, aby przydzielił pamięć i nadał temu obszarowi pamięci symboliczną nazwę.

Strukturę można opisać w programie tylko raz, ale można ją zdefiniować dowolną ilość razy.

Opis szablonu struktury

Opis szablonu struktury ma następującą składnię:

nazwa_struktury STRUC

nazwa_struktury ENDS

Tutaj to sekwencja dyrektyw opisujących dane db, dw, dd, dq oraz dt.

Ich operandy określają wielkość pól i, jeśli to konieczne, wartości początkowe. Wartości te zostaną prawdopodobnie zainicjalizowane do odpowiednich pól podczas definiowania struktury.

Jak zauważyliśmy opisując szablon, pamięć nie jest alokowana, ponieważ jest to tylko informacja dla tłumacza.

Lokalizacja Szablon w programie może być dowolny, ale zgodnie z logiką translatora jednoprzebiegowego musi znajdować się do miejsca, w którym zdefiniowana jest zmienna o typie tej struktury. Oznacza to, że opisując zmienną z typem jakiejś struktury w segmencie danych, jej szablon musi być umieszczony na początku segmentu danych lub przed nim.

Rozważmy pracę ze strukturami na przykładzie modelowania bazy danych pracowników danego działu.

Dla uproszczenia, aby uciec od problemów z przeliczaniem informacji przy wpisywaniu, uzgodnimy, że wszystkie pola są symboliczne.

Zdefiniujmy strukturę rekordów tej bazy danych za pomocą następującego szablonu:

Definiowanie danych o typie struktury

Aby wykorzystać strukturę opisaną za pomocą szablonu w programie, należy zdefiniować zmienną o typie tej struktury. W tym celu używana jest następująca składnia:

[nazwa zmiennej] nazwa_struktury

    nazwa zmiennej- identyfikator zmiennej tego typu strukturalnego.

    Nazwa zmiennej jest opcjonalna. Jeśli tego nie określisz, po prostu zostanie przydzielony obszar pamięci o rozmiarze sumy długości wszystkich elementów konstrukcji.

    lista wartości- oddzieloną przecinkami listę wartości początkowych elementów konstrukcji, umieszczoną w nawiasach ostrych.

    Jego przydział jest również opcjonalny.

    Jeżeli lista jest niekompletna, to wszystkie pola struktury dla tej zmiennej są inicjowane wartościami z szablonu, jeśli takie istnieją.

    Dozwolone jest inicjowanie poszczególnych pól, ale w tym przypadku brakujące pola muszą być oddzielone przecinkami. Brakujące pola zostaną zainicjowane wartościami z szablonu struktury. Jeżeli definiując nową zmienną z typem tej struktury zgadzamy się ze wszystkimi wartościami pól w jej szablonie (czyli domyślnie ustawionymi), to wystarczy wpisać nawiasy kątowe.

    Na przykład: zwycięski robotnik.

Na przykład zdefiniujmy kilka zmiennych o typie struktury opisanym powyżej.

Metody pracy ze strukturą

Ideą wprowadzenia typu strukturalnego do dowolnego języka programowania jest połączenie zmiennych różnych typów w jeden obiekt.

Język musi mieć możliwość dostępu do tych zmiennych w ramach określonej instancji struktury. Aby odwołać się do pola o jakiejś strukturze w poleceniu, używany jest specjalny operator - symbol ". " (punkt)... Jest używany w następującej składni:

    adres_wyrażenie- identyfikator zmiennej pewnego typu strukturalnego lub wyrażenie w nawiasie zgodnie z regułami składniowymi wskazanymi poniżej (rys. 1);

    nazwa_pola_struktury- nazwa pola z szablonu struktury.

    W rzeczywistości jest to również adres, a raczej przesunięcie pola od początku struktury.

Tak więc operator " . „(kropka) ocenia wyrażenie

Ryż. 5. Składnia wyrażenia adresowego w operatorze dostępu do pola struktury

Zademonstrujmy na przykładzie zdefiniowanej przez nas struktury pracownik niektóre techniki pracy ze strukturami.

Na przykład wyodrębnij w topór wartości pól z wiekiem. Skoro jest mało prawdopodobne, aby wiek osoby pełnosprawnej przekroczył 99 lat, to po umieszczeniu zawartości tego pola znakowego w rejestrze topór wygodnie będzie przekonwertować go na reprezentację binarną za pomocą polecenia aad.

Bądź ostrożny, ponieważ ze względu na zasadę przechowywania danych „Najmniej znaczący bajt przynajmniej znaczący adres” najwyższa cyfra wieku zostanie umieszczona w glin, a najmłodsi - in ach.

Aby dostosować, po prostu użyj polecenia xchg al, ach:

mov ax, słowo ptr sotr1.age; w al age sotr1

lub możesz to zrobić:

Dalsza praca z tablicą struktur odbywa się w taki sam sposób, jak z tablicą jednowymiarową. Pojawia się tutaj kilka pytań:

A co z rozmiarem i jak zorganizować indeksowanie elementów tablicy?

Podobnie jak w przypadku innych identyfikatorów zdefiniowanych w programie, translator przypisuje nazwę typu struktury oraz nazwę zmiennej z typem struktury do atrybutu type. Wartością tego atrybutu jest rozmiar w bajtach zajmowany przez pola tej struktury. Możesz pobrać tę wartość za pomocą operatora rodzaj.

Po poznaniu rozmiaru wystąpienia struktury nie jest trudno zorganizować indeksowanie w tablicy struktur.

Na przykład:

Jak skopiować pole z jednej struktury do odpowiedniego pola innej struktury? Albo jak skopiować całą strukturę? Skopiujmy pole nam trzeci pracownik w terenie nam piąty pracownik:

mas_sotr pracownik 10 dup ()

mov bx, przesunięcie mas_sotr

mov si, (typ worker) * 2; si = 77 * 2

mov di, (typ pracownik) * 4; si = 77 * 4

Wydaje mi się, że rzemiosło programisty prędzej czy później sprawia, że ​​człowiek wygląda na dobrą gospodynię domową. On, podobnie jak ona, nieustannie szuka, gdzie coś zapisać, cofnąć i zrobić wspaniały obiad z minimum produktów. A jeśli to się uda, moralną satysfakcję uzyskuje się nie mniej, a może więcej, niż ze wspaniałej kolacji z gospodynią domową. Wydaje mi się, że stopień tej satysfakcji zależy od stopnia miłości do twojego zawodu.

Z drugiej strony sukcesy w rozwoju oprogramowania i sprzętu nieco rozluźniają programistę i dość często obserwuje się sytuację podobną do znanego przysłowia o locie i słoniu - aby rozwiązać jakiś drobny problem, używa się ciężkich środków, których skuteczność w ogólnym przypadku ma znaczenie tylko przy realizacji stosunkowo dużych projektów.

Obecność następujących dwóch rodzajów danych w języku prawdopodobnie tłumaczy się chęcią „gospodyni” do jak najefektywniejszego wykorzystania obszaru roboczego stołu (RAM) podczas przygotowywania jedzenia lub umieszczania produktów (dane programu ).

Struktura instrukcji w języku asemblerowym Programowanie na poziomie instrukcji maszynowych jest minimalnym poziomem, na którym możliwe jest programowanie komputerowe. Zestaw instrukcji maszynowych musi być wystarczający do wykonania wymaganych czynności poprzez wydawanie instrukcji do sprzętu maszyny. Każda instrukcja maszynowa składa się z dwóch części: operacyjnej, która definiuje „co robić” oraz operandu, który definiuje obiekty przetwarzania, czyli co robić dalej. Instrukcja maszynowa mikroprocesora napisana w języku asemblerowym jest pojedynczym wierszem o następującej postaci: instrukcja etykieta / operand(y) dyrektywy; komentarze Etykieta, komenda/dyrektywa i operand są oddzielone przynajmniej jednym znakiem spacji lub tabulacji. Operandy poleceń są oddzielone przecinkami.

Struktura instrukcji w asemblerze Instrukcja w asemblerze mówi tłumaczowi, jakie działanie powinien podjąć mikroprocesor. Dyrektywy asemblera to parametry określone w tekście programu, które wpływają na proces asemblacji lub właściwości pliku wyjściowego. Operand definiuje początkową wartość danych (w segmencie danych) lub elementy, na które polecenie ma działać (w segmencie kodu). Instrukcja może mieć jeden lub dwa operandy lub nie mieć operandów. Liczba operandów jest domyślnie określona przez kod komendy. Jeśli polecenie lub dyrektywa ma być kontynuowane w następnym wierszu, używany jest znak odwrotnego ukośnika: "". Domyślnie asembler nie rozróżnia wielkich i małych liter podczas pisania poleceń i dyrektyw. Przykłady dyrektywy i polecenia Count db 1; Nazwa, dyrektywa, jeden operand mov eax, 0; Polecenie, dwa argumenty

Identyfikatory to sekwencje prawidłowych znaków używanych do oznaczania nazw zmiennych i nazw etykiet. Identyfikator może składać się z jednego lub więcej z następujących znaków: wszystkie litery alfabetu łacińskiego; liczby od 0 do 9; znaki specjalne: _, @, $,? ... Kropka może być użyta jako pierwszy znak etykiety. Zarezerwowane nazwy asemblerów (dyrektywy, operatory, nazwy poleceń) nie mogą być używane jako identyfikatory. Pierwszy znak identyfikatora musi być literą lub znakiem specjalnym. Maksymalna długość identyfikatora to 255 znaków, ale tłumacz akceptuje pierwsze 32, ignoruje resztę. Wszystkie etykiety napisane w wierszu, który nie zawiera dyrektywy asemblera, muszą kończyć się dwukropkiem ":". Etykieta, polecenie (dyrektywa) i operand nie muszą zaczynać się w określonej pozycji w łańcuchu. Zaleca się zapisanie ich w kolumnie dla lepszej czytelności programu.

Etykiety Wszystkie etykiety napisane w wierszu, który nie zawiera dyrektywy asemblera, muszą kończyć się dwukropkiem ":". Etykieta, polecenie (dyrektywa) i operand nie muszą zaczynać się w określonej pozycji w łańcuchu. Zaleca się zapisanie ich w kolumnie dla lepszej czytelności programu.

Komentarze Używanie komentarzy w programie poprawia przejrzystość, zwłaszcza gdy intencja zestawu instrukcji nie jest jasna. Komentarze zaczynają się w dowolnym wierszu w module źródłowym od średnika (;). Wszystkie znaki na prawo od „; »Na końcu wiersza jest komentarz. Komentarz może zawierać dowolne znaki, które można wydrukować, w tym spację. Komentarz może obejmować cały wiersz lub podążać za poleceniem w tym samym wierszu.

Struktura programu w języku asemblerowym Program napisany w języku asemblerowym może składać się z kilku części, zwanych modułami, w każdym z których można zdefiniować jeden lub więcej segmentów danych, stosu i kodu. Każdy kompletny program asemblerowy musi zawierać jeden moduł główny, czyli główny, od którego rozpoczyna się jego wykonanie. Moduł może zawierać segmenty programu, segmenty danych oraz stos zadeklarowany przy użyciu odpowiednich dyrektyw.

Modele pamięci Przed zadeklarowaniem segmentów należy określić model pamięci za pomocą dyrektywy. MODEL modyfikator model_pamięci, konwencja_wywołania, typ_systemu, parametr_stosu Podstawowe modele pamięci języka asemblerowego: Model pamięci Adresowanie kodu Adresowanie danych System operacyjny Przeplatanie kodu i danych MAŁY BLISKO MS-DOS Dozwolony MAŁY BLISKO MS-DOS, Windows Nie ŚREDNI BLISKO MS-DOS, Windows Brak KOMPAKTOWY BLISKI MS-DOS, Windows Nie DUŻY DALEKI MS-DOS, Windows Brak OGROMNEGO DALEKIEGO MS-DOS, Windows Brak BLISKO Windows 2000, Windows XP, Windows Dozwolony PŁASKI BLISKI NT,

Modele pamięci Mały model działa tylko w 16-bitowych aplikacjach MS-DOS. W tym modelu wszystkie dane i kod znajdują się w jednym fizycznym segmencie. Rozmiar plik programu w tym przypadku nie przekracza 64 KB. Mały model obsługuje jeden segment kodu i jeden segment danych. Dane i kod są adresowane jak najbliżej podczas korzystania z tego modelu. Model średni obsługuje wiele segmentów kodu i jeden segment danych, przy czym wszystkie łącza w segmentach kodu są domyślnie uważane za dalekie, a łącza w segmencie danych jako bliskie. Kompaktowy model obsługuje wiele segmentów danych przy użyciu dalekiego adresowania danych i jednego bliskiego segmentu danych. Duży model obsługuje wiele segmentów kodu i wiele segmentów danych. Domyślnie wszystkie odwołania do kodu i danych są uważane za dalekie. Ogromny model jest prawie odpowiednikiem modelu z dużą pamięcią.

Modele pamięci Model płaski zakłada niesegmentowaną konfigurację programu i jest używany tylko w 32-bitowych systemach operacyjnych. Ten model jest podobny do małego modelu, ponieważ dane i kod są zawarte w jednym 32-bitowym segmencie. Opracowanie programu dla modelu płaskiego przed dyrektywą. wzór płaski należy umieścić jedną z dyrektyw:. 386,. 486,. 586 lub. 686. Wybór dyrektywy wyboru procesora określa zestaw instrukcji dostępnych podczas pisania programów. Litera p po dyrektywie wyboru procesora oznacza chroniony tryb pracy. Adresowanie danych i kodu jest bliskie, a wszystkie adresy i wskaźniki są 32-bitowe.

Modele pamięci. MODEL modyfikator memory_model, call_convention, OS_type, stack_parameter Parametr modyfikatora służy do definiowania typów segmentów i może przyjmować następujące wartości: use 16 (segmenty wybranego modelu są używane jako 16-bitowe) use 32 (segmenty wybranego modelu są używane jako 32-bitowe). Parametr call_convention służy do określenia sposobu przekazywania parametrów podczas wywoływania procedury z innych języków, w tym języków wysokiego poziomu (C++, Pascal). Parametr może przyjmować następujące wartości: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Modele pamięci. Modyfikator MODEL model_pamięci, konwencja_połączeń, typ_os, parametr_stosu OS_type jest domyślną wartością OS_DOS i jest obecnie jedyną obsługiwaną wartością tego parametru. Parametr_stosu jest ustawiony na: NEARSTACK (rejestr SS to DS, obszary danych i stosu znajdują się w tym samym fizycznym segmencie) FARSTACK (rejestr SS nie jest równy DS, obszary danych i stosu znajdują się w różnych segmentach fizycznych). Wartość domyślna to NEARSTACK.

Przykład programu „nic nie robienie”. 686 P. MODEL PŁASKI, STDCALL. DANE. CODE START: RET END START RET - polecenie mikroprocesorowe. Zapewnia prawidłowe zakończenie programu. Pozostała część programu związana jest z pracą tłumacza. ... 686 P — Dozwolone polecenia trybu chronionego Pentium 6 (Pentium II). Ta dyrektywa wybiera obsługiwany zestaw instrukcji asemblera przez określenie modelu procesora. ... MODEL FLAT, stdcall to płaski model pamięci. Ten model pamięci jest używany w systemie operacyjnym Windows. stdcall to stosowana konwencja wywoływania procedur.

Przykład programu „nic nie robienie”. 686 P. MODEL PŁASKI, STDCALL. DANE. KOD POCZĄTEK: POWRÓT KONIEC START. DATA to segment programu zawierający dane. Ten program nie używa stosu, więc segment. Brak STOSOWANIA. ... KOD to segment programu zawierający kod. START to etykieta. END START - koniec programu i komunikat do kompilatora, że ​​program należy uruchomić z etykiety START. Każdy program musi zawierać dyrektywę END oznaczającą koniec kodu źródłowego programu. Wszystkie wiersze następujące po dyrektywie END są ignorowane.Etykieta określona po dyrektywie END informuje tłumacza o nazwie głównego modułu, z którego program startuje. Jeżeli program zawiera jeden moduł, etykietę po dyrektywie END można pominąć.

Tłumacze języka asemblera Tłumacz to program lub środki techniczne który konwertuje program w jednym z języków programowania na program w języku docelowym zwanym kodem obiektowym. Oprócz obsługi mnemoniki instrukcji maszynowych, każdy tłumacz ma swój własny zestaw dyrektyw i narzędzi makr, które często są niekompatybilne z niczym. Główne typy translatorów języka asemblera: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - darmowy asembler wieloprzebiegowy autorstwa Tomasza Grishtara (Polski), NASM (Netwide Assembler) - darmowy asembler dla Architektura Intel x 86, został stworzony przez Simona Tathama we współpracy z Julianem Hallem i jest obecnie rozwijany przez mały zespół programistów na Source. Fałszować. Internet.

Src = "https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt = "(! LANG: Microsoft Broadcast Visual Studio 2005 1) Utwórz projekt wybierając Plik-> Nowy-> Projekt i "> Tłumaczenie programu do Microsoft Visual Studio 2005 1) Utwórz projekt wybierając Plik-> Nowy-> Projekt i określając nazwę projektu (hello.prj) oraz typ projektu: Win 32 Project. opcje dodatkowe kreatora projektu określ „Pusty projekt”.

Src = "https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt = "(! LANG: Transmisja programu do Microsoft Visual Studio 2005 2) W drzewie projektu (Widok-> Eksplorator rozwiązań) Dodaj"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Tłumaczenie programu na Microsoft Visual Studio 2005 3) Wybierz typ pliku Code C++, ale określ nazwę z rozszerzeniem. jako M:

Tłumaczenie programu na Microsoft Visual Studio 2005 5) Ustaw opcje kompilatora. Wybierz według prawy przycisk w pliku projektu menu Custom Build Rules...

Tłumaczenie programu na Microsoft Visual Studio 2005 i w wyświetlonym oknie wybierz Microsoft Macro Assembler.

Tłumaczenie programu w Microsoft Visual Studio 2005 Sprawdź, klikając w powitanie prawym przyciskiem myszy. asm drzewa projektu z menu Właściwości i ustaw Ogólne->Narzędzie: Microsoft Macro Assembler.

Src = "https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt = "(! LANG: Emisja programu do Microsoft Visual Studio 2005 6) Skompiluj plik wybierając Build-> Build hello. Prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Programowanie w systemie operacyjnym Windows Programowanie w systemie operacyjnym Windows opiera się na wykorzystaniu funkcji API (Application Program Interface, tj. aplikacja oprogramowania). Ich liczba sięga 2000. Program dla Windows składa się w dużej mierze z takich połączeń. Cała interakcja z urządzeniami zewnętrznymi i zasobami systemu operacyjnego odbywa się z reguły za pośrednictwem takich funkcji. Sala operacyjna System Windows używa płaskiego modelu pamięci. Adres dowolnej komórki pamięci będzie określony przez zawartość jednego rejestru 32-bitowego. Istnieją 3 rodzaje struktur programu dla systemu Windows: dialog (okno główne - okno dialogowe), struktura konsoli lub bez okien, struktura klasyczna (okno, szkielet).

Połączenie Funkcje systemu Windows API W pliku pomocy dowolna funkcja API jest reprezentowana jako typ nazwa_funkcji (FA 1, FA 2, FA 3) Typ - typ zwracanej wartości; ФАх - lista argumentów formalnych w kolejności ich występowania, np. int Message. Box (HWND h. Wnd, LPCTSTR lp. Tekst, LPCTSTR lp. Podpis, UINT u. Typ); Ta funkcja wyświetla okno z komunikatem i przyciskiem (lub przyciskami) wyjścia. Znaczenie parametrów: godz. Wnd - uchwyt do okna, w którym pojawi się okno wiadomości, lp. Tekst - tekst, który pojawi się w oknie, lp. Podpis - tekst w tytule okna, u. Typ - typ okna, w szczególności można zdefiniować ilość przycisków wyjścia.

Wywoływanie funkcji Windows API w Message. Box (HWND h. Wnd, LPCTSTR lp. Tekst, LPCTSTR lp. Podpis, UINT u. Typ); Prawie wszystkie parametry funkcji API są w rzeczywistości 32-bitowymi liczbami całkowitymi: HWND jest 32-bitową liczbą całkowitą, LPCTSTR jest 32-bitowym wskaźnikiem do łańcucha, UINT jest 32-bitową liczbą całkowitą. Przyrostek „A” jest często dołączany do nazwy funkcji w celu przejścia do nowszych wersji funkcji.

Wywoływanie funkcji Windows API w Message. Box (HWND h. Wnd, LPCTSTR lp. Tekst, LPCTSTR lp. Podpis, UINT u. Typ); Używając MASM, musisz dodać @N N na końcu nazwy - liczbę bajtów, które przekazane argumenty zajmują na stosie. W przypadku funkcji API Win 32 liczba ta może być zdefiniowana jako liczba argumentów n razy 4 (bajty w każdym argumencie): N = 4 * n. Komenda CALL asemblera jest używana do wywołania funkcji. W tym przypadku wszystkie argumenty funkcji są do niej przekazywane przez stos (polecenie PUSH). Kierunek przekazywania argumentów: OD LEWEJ DO PRAWEJ - OD DOŁU DO GÓRY. Pierwszym argumentem, który należy odłożyć na stos, jest u. Rodzaj. Połączenie określona funkcja będzie wyglądać tak: CALL Wiadomość. Skrzynka. [e-mail chroniony]

Wywoływanie funkcji Windows API w Message. Box (HWND h. Wnd, LPCTSTR lp. Tekst, LPCTSTR lp. Podpis, UINT u. Typ); Wynikiem wykonania dowolnej funkcji API jest z reguły liczba całkowita zwracana w rejestrze EAX. Dyrektywa OFFSET jest "przesunięciem segmentu" lub, w kategoriach wysokiego poziomu, "wskaźnikiem" do początku linii. Dyrektywa EQU, podobnie jak #define w języku C, definiuje stałą. Dyrektywa EXTERN mówi tłumaczowi, że funkcja lub identyfikator są zewnętrzne względem danego modułu.

Przykład programu „Witam wszystkich!” ... 686 P. MODEL PŁASKI, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Mój pierwszy program", 0 STR 2 DB "Witam wszystkich!", 0 HW DD? ZEWNĘTRZNA Wiadomość. Skrzynka. [e-mail chroniony]: BLISKO. KOD START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Wiadomość. Skrzynka. [e-mail chroniony] POWRÓT KONIEC START

Dyrektywa INVOKE Translator języka MASM umożliwia również uproszczenie wywoływania funkcji za pomocą narzędzia makr - dyrektywa INVOKE: funkcja INVOKE, parametr1, parametr2, ... W tym przypadku nie ma potrzeby dodawania @16 do wywołanie funkcji; parametry są zapisywane dokładnie w kolejności, w jakiej są wymienione w opisie funkcji. parametry są umieszczane na stosie za pomocą translatora. aby skorzystać z dyrektywy INVOKE należy posiadać opis prototypu funkcji za pomocą dyrektywy PROTO w postaci: Message. Skrzynka. A PROTO: DWORD,: DWORD Jeśli program korzysta z wielu funkcji API Win 32, zaleca się użycie dyrektywy include C: masm 32includeuser 32. inc

DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz czytać Dzwon?
Bez spamu