DZWON

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

Polecenia asemblera (Wykład)

PLAN WYKŁADU

1. Główne grupy operacji.

Pentium.

1. Główne grupy operacji

Mikroprocesory wykonują zestaw instrukcji realizujących następujące główne grupy operacji:

operacje spedycyjne,

działania arytmetyczne,

operacje logiczne,

operacje zmianowe,

operacje porównawcze i testowe,

operacje bitowe,

Operacje zarządzania programem;

Operacje kontroli procesora.

2. Mnemokody poleceń procesora Pentium

Przy opisie poleceń zwykle stosuje się ich oznaczenia mnemoniczne (kody mnemoniczne), które służą do określenia polecenia podczas programowania na język programowania. Dla różnych wersji asemblera, kody mnemoniczne niektórych poleceń mogą się różnić. Na przykład w przypadku polecenia wywoływania podprogramu używany jest kod mnemonicznyPOŁĄCZENIE lub JSR ("Skocz do podprogram”). Jednak kody mnemoniczne większości poleceń dla głównych typów mikroprocesorów są takie same lub nieznacznie się różnią, ponieważ są to skróty odpowiednich angielskich słów, które definiują wykonywaną operację. Rozważ mnemoniki poleceń przyjęte dla procesorów Pentium.

Polecenia do przodu. Głównym dowództwem tej grupy jest polecenieMOV , który zapewnia transfer danych między dwoma rejestrami lub między rejestrem a komórką pamięci. Niektóre mikroprocesory realizują transfer między dwiema komórkami pamięci, a także grupowy transfer zawartości kilku rejestrów z pamięci. Na przykład mikroprocesory z rodziny 68 Motorola XXX wykonaj polecenieRUSZAJ SIĘ , który zapewnia transfer z jednej komórki pamięci do drugiej oraz poleceniePRZESUŃ , który zapisuje do pamięci lub ładuje z pamięci zawartość danego zbioru rejestrów (do 16 rejestrów). ZespółXCHG dokonuje wzajemnej wymiany zawartości dwóch rejestrów procesora lub rejestru i komórki pamięci.

Polecenia wejściowe W i wyjście NA ZEWNĄTRZ realizacji transferu danych z rejestru procesora do urządzenia zewnętrznego lub odbioru danych z urządzenia zewnętrznego do rejestru. Te polecenia określają numer urządzenia interfejsu (port we/wy), przez który przesyłane są dane. Zauważ, że wiele mikroprocesorów nie ma specjalnych poleceń dostępu do urządzeń zewnętrznych. W takim przypadku wprowadzanie i wyprowadzanie danych w systemie odbywa się za pomocą poleceniaMOV , który określa adres wymaganego urządzenia interfejsu. Tym samym urządzenie zewnętrzne jest adresowane jako komórka pamięci, a w przestrzeni adresowej przydzielana jest określona sekcja, w której znajdują się adresy urządzeń interfejsowych (portów) podłączonych do systemu.

Polecenia do operacji arytmetycznych. Główne polecenia w tej grupie to dodawanie, odejmowanie, mnożenie i dzielenie, które mają szereg opcji. Polecenia dodawania DODAJ i odejmowanie POD wykonać odpowiednie operacje zcposiadanie dwóch rejestrów, rejestru i komórki pamięci, lub użycie operandu bezpośredniego. Drużyny OGŁOSZENIE C , SB B wykonać dodawanie i odejmowanie, biorąc pod uwagę wartość atrybutuC, ustawiony podczas tworzenia przelewu w trakcie wykonywania poprzedniej operacji. Za pomocą tych poleceń realizowane jest sekwencyjne dodawanie operandów, których liczba cyfr przekracza pojemność procesora. Zespół NEG zmienia znak operandu, przekształcając go w dopełnienie do dwóch.

Operacje mnożenia i dzielenia można wykonywać na liczbach ze znakiem (poleceniaI UM, I DIV ) lub bez znaku (polecenia MUL, DIV ). Wynik operacji znajduje się w rejestrze. Podczas mnożenia (poleceniaMUL , IMUL ) daje wynik dwucyfrowy, który wykorzystuje dwa rejestry do dostosowania. Podczas dzielenia (poleceniaDIV , IDIV ) jako dywidendę stosuje się operand dwucyfrowy, umieszczony w dwóch rejestrach, w wyniku czego iloraz i reszta są zapisywane do dwóch rejestrów.

Drużyny operacje logiczne . Prawie wszystkie mikroprocesory wykonują operacje logiczne AND, OR, Exclusive OR, które są wykonywane na bitach operandu o tej samej nazwie za pomocą poleceń ORAZ, LUB, X LUB . Operacje wykonywane są na zawartości dwóch rejestrów, rejestru i komórki pamięci, lub za pomocą operandu bezpośredniego. Zespół NIE Odwraca wartość każdego bitu operandu.

Polecenia przesunięcia. Mikroprocesory wykonują arytmetyczne, logiczne i cykliczne przesunięcia adresowanych operandów o jeden lub więcej bitów. Operand, który ma być przesunięty, może znajdować się w rejestrze lub lokacji pamięci, a liczba bitów przesunięcia jest określona przy użyciu operandu bezpośredniego zawartego w instrukcji lub określona przez zawartość określonego rejestru. Znak przeniesienia jest zwykle zaangażowany w realizację zmianyCw rejestrze statusu (SR lub EFLAGI), który zawiera ostatni bit operandu, który jest wyciągany z rejestru lub lokalizacji pamięci.

Polecenia porównawcze i testujące . Porównanie operandów odbywa się zwykle za pomocą poleceniaCMP , który wykonuje odejmowanie operandów z ustawieniem wartości cech N, Z, V, C w rejestrze stanu zgodnie z wynikiem. W takim przypadku wynik odejmowania nie jest zapisywany, a wartości operandów nie ulegają zmianie. Późniejsza analiza uzyskanych wartości charakterystycznych pozwala określić wartość względną (>,<, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Niektóre mikroprocesory wykonują polecenie testowe TST , który jest wariantem instrukcji porównania z pojedynczym argumentem. Po wykonaniu tego polecenia znaki są ustawiane N, Z zgodnie ze znakiem i wartością (równą lub niezerową) adresowanego operandu.

Instrukcje obsługi bitów . Te polecenia ustawiają wartość atrybutuCw rejestrze stanu zgodnie z wartością testowanego bitubn w zaadresowanym operandzie. W niektórych mikroprocesorach, zgodnie z wynikiem testu, ustawiany jest znakZ. Numer bitu testowegonjest ustawiana albo przez zawartość rejestru określonego w poleceniu, albo przez bezpośredni operand.

Polecenia z tej grupy implementują różne opcje zmiany testowanego bitu BT utrzymuje wartość tego bitu niezmienioną.Command B T S po testach ustawia wartość bn=1, a polecenie B T C - oznaczający bn=0.Polecenie B T C odwraca wartość bitu bn po przetestowaniu.

Operacje zarządzania programem. Do sterowania programem używana jest duża liczba poleceń, wśród których są:

- bezwarunkowe polecenia przekazania sterowania;

- polecenia skoku warunkowego;

- polecenia do organizowania cykli programu;

- polecenia przerwania;

- polecenia zmiany funkcji.

Bezwarunkowego przekazania kontroli dokonuje dowództwoJMP , który ładuje się do licznika programuPCnowa zawartość, która jest adresem następnego polecenia do wykonania. Ten adres jest albo bezpośrednio określony w poleceniuJMP (adres bezpośredni) lub liczony jako suma aktualnej treściPCi offset określony w poleceniu, który jest liczbą ze znakiem (adresowanie względne). DlategoPCzawiera adres następnego polecenia programu, to ostatnia metoda ustawia adres przejścia, przesunięcie względem następnego adresu o podaną liczbę bajtów. Jeżeli offset jest dodatni, to następuje przejście do kolejnych poleceń programu, jeżeli offset jest ujemny, do poprzednich.

Podprogram jest również wywoływany przez bezwarunkowe przekazanie kontroli za pomocą poleceniaPOŁĄCZENIE (lub JSR ). Jednak w tym przypadku przed załadowaniem doPC nową treść określającą adres pierwszej instrukcji podprogramu, konieczne jest zapisanie jej aktualnej wartości (adresu następnej instrukcji) w celu zapewnienia powrotu do programu głównego po wykonaniu podprogramu (lub do poprzedni podprogram podczas zagnieżdżania podprogramów). Instrukcje skoku warunkowego (gałęzie programu) są ładowane doPCnowa treść, jeśli spełnione są określone warunki, które są zwykle ustawiane zgodnie z aktualną wartością różnych atrybutów w rejestrze statusu. Jeśli warunek nie jest spełniony, wykonywane jest następne polecenie programu.

Polecenia zarządzania cechami zapewniają pisanie – odczytywanie zawartości rejestru statusu, w którym przechowywane są cechy, a także zmianę wartości poszczególnych cech. Na przykład procesory Pentium realizują polecenia LAHF oraz SAHF , który ładuje młodszy bajt, który zawiera znaki, z rejestru statusu EFLAG za niski bajt rejestru EAX i dopełnieniem małym bajtem EFLAGI z rejestru E AX.. Polecenia CLC, STC ustawić wartości flagi transferu CF=0, CF=1 oraz komendy CMC powoduje odwrócenie wartości tej funkcji. Ponieważ cechy określają przebieg wykonywania programu podczas skoków warunkowych, instrukcje zmiany cechy są zwykle używane do sterowania programem.

Polecenia sterujące procesorem . Ta grupa obejmuje polecenia zatrzymania, brak działania oraz szereg poleceń, które określają tryb działania procesora lub jego poszczególnych bloków. ZespółHLT kończy wykonywanie programu i wprowadza procesor w stan zatrzymania, z którego wyjście następuje po otrzymaniu sygnałów przerwania lub restartu ( Resetowanie). Zespół NOP Instrukcja („pusta”), która nie powoduje wykonania żadnych operacji, służy do implementacji opóźnień programu lub wypełnienia luk powstałych w programie.

Zespoły specjalne CLI, STI wyłączyć i włączyć obsługę żądań przerwań. W procesorach Pentium służy do tego bit kontrolny (flaga)JEŚLI w rejestrze EFLAGI.

Wiele nowoczesnych mikroprocesorów wydaje polecenie identyfikacyjne, które pozwala użytkownikowi lub innym urządzeniom uzyskać informacje o rodzaju procesora zastosowanego w danym systemie. W procesorach Pentuim po to jest polecenie CPUID , podczas którego niezbędne dane o procesorze trafiają do rejestrów EAX,zły,ECX,EDX a następnie mogą być odczytywane przez użytkownika lub system operacyjny.

W zależności od trybów pracy zaimplementowanych przez procesor oraz określonych typów przetwarzanych danych, zestaw poleceń wykonywalnych może być znacznie rozszerzony.

Niektóre procesory wykonują operacje arytmetyczne BCD lub wykonują specjalne instrukcje korekcji wyników podczas przetwarzania takich liczb. Wiele wysokowydajnych procesorów obejmuje FPU - jednostka przetwarzania liczb c „zmiennoprzecinkowy”.

W wielu nowoczesnych procesorach zaimplementowane jest przetwarzanie grupowe kilku liczb całkowitych lub liczb. c „ruchomy punkt” jednym poleceniem zgodnie z zasadą SIMD („Pojedyncza instrukcja – wiele danych ”) - „Jedno polecenie – Dużo danych”. Jednoczesne wykonywanie operacji na kilku operandach znacznie zwiększa wydajność procesora podczas pracy z danymi wideo i audio. Takie operacje są szeroko stosowane w przetwarzaniu obrazu, przetwarzaniu sygnału audio i innych zastosowaniach. Aby wykonać te operacje, do procesorów wprowadzane są specjalne bloki, które implementują odpowiednie zestawy instrukcji, które w różnych typach procesorów ( Pentium, Athlon) dostał nazwęMMX (“ Milti-Rozszerzenie multimedialne ”) – Rozszerzenie Multimedialne,SSE(„Rozszerzenie Streaming SIMD”) – Streaming SIMD - rozbudowa, “3 DRozbudowa- Rozszerzenie 3D.

Cecha charakterystyczna procesorów firmy Intel , począwszy od modelu 80286, jest priorytetem kontroli dostępu do pamięci, który jest zapewniany, gdy procesor pracuje w trybie chronionego adresu wirtualnego -” Tryb obronny " (tryb obronny). Do realizacji tego trybu wykorzystywane są specjalne grupy poleceń, które służą do organizowania ochrony pamięci zgodnie z przyjętym algorytmem priorytetowego dostępu.

UNIWERSYTET NARODOWY UZBEKISTANU IM. MIRZO ULUGBEK

WYDZIAŁ TECHNOLOGII KOMPUTEROWYCH

Na temat: Analiza semantyczna pliku EXE.

Zakończony:

Taszkent 2003.

Przedmowa.

Język asemblera i struktura instrukcji.

Struktura pliku EXE (parsowanie semantyczne).

Struktura pliku COM.

Jak wirus działa i rozprzestrzenia się.

Demontaż.

Programy.

Przedmowa

Zawód programisty jest niesamowity i niepowtarzalny. W naszych czasach nie można sobie wyobrazić nauki i życia bez najnowszych technologii. Wszystko, co wiąże się z działalnością człowieka, nie jest kompletne bez technologii komputerowej. A to przyczynia się do jego wysokiego rozwoju i perfekcji. Nawet jeśli rozwój komputerów osobistych rozpoczął się nie tak dawno temu, ale w tym czasie podjęto kolosalne kroki w oprogramowaniu i przez długi czas produkty te będą szeroko stosowane. Dziedzina wiedzy komputerowej eksplodowała, podobnie jak związana z nią technologia. Jeśli nie weźmiemy pod uwagę strony komercyjnej, to możemy powiedzieć, że w tym obszarze aktywności zawodowej nie ma obcych. Wielu angażuje się w rozwój programów nie dla zysku lub zarobku, ale z własnej woli, z pasji. Oczywiście nie powinno to wpływać na jakość programu, aw tym biznesie, że tak powiem, istnieje konkurencja i zapotrzebowanie na wysoką jakość wykonania, stabilną pracę i spełnienie wszystkich wymagań naszych czasów. Tutaj również warto zwrócić uwagę na pojawienie się w latach 60-tych mikroprocesorów, które zastąpiły dużą liczbę zestawów lamp. Istnieje kilka odmian mikroprocesorów, które bardzo się od siebie różnią. Te mikroprocesory różnią się między sobą pojemnością bitową i wbudowanymi poleceniami systemowymi. Najczęstsze z nich to: Intel, IBM, Celeron, AMD itp. Wszystkie te procesory są powiązane z zaawansowaną architekturą procesorów Intel. Rozprzestrzenianie się mikrokomputerów spowodowało zmianę podejścia do języka asemblera z dwóch głównych powodów. Po pierwsze, programy napisane w języku asemblerowym wymagają znacznie mniej pamięci i czasu wykonywania. Po drugie, znajomość języka asemblera i wynikającego z niego kodu maszynowego daje zrozumienie architektury maszyny, co jest rzadko zapewniane podczas pracy w języku wysokiego poziomu. Podczas gdy większość profesjonalistów programistycznych tworzy programy w językach wysokiego poziomu, takich jak Pascal, C lub Delphi, które są łatwiejsze do pisania programów, najpotężniejsze i najbardziej wydajne oprogramowanie jest napisane w całości lub częściowo w języku asemblerowym. Języki wysokiego poziomu zostały zaprojektowane tak, aby uniknąć szczególnych cech technicznych poszczególnych komputerów. Z kolei język asemblerowy jest dostosowany do specyfiki procesora. Dlatego, aby napisać program w asemblerze dla konkretnego komputera, trzeba znać jego architekturę. Obecnie typem głównego oprogramowania jest plik EXE. Biorąc pod uwagę pozytywne aspekty tego, autor programu może być pewien jego nienaruszalności. Ale często jest to dalekie od przypadku. Istnieje również deasembler. Za pomocą deasemblera możesz znaleźć przerwania i kody programów. Osobie dobrze zorientowanej w asemblerze nie będzie trudno przerobić cały program według własnego gustu. Być może stąd bierze się najbardziej nierozwiązywalny problem - wirus. Dlaczego ludzie piszą wirusy? Niektórzy zadają to pytanie ze zdziwieniem, inni ze złością, ale mimo wszystko są osoby, które są zainteresowane tym zadaniem nie z punktu widzenia wyrządzenia jakiejś szkody, ale zainteresowania programowaniem systemu. Wirusy są pisane z różnych powodów. Niektórzy lubią wywołania systemowe, inni poprawiają swoją wiedzę w asemblerze. Postaram się to wszystko wyjaśnić w mojej pracy semestralnej. Mówi również nie tylko o strukturze pliku EXE, ale także o języku asemblera.

^ Język asemblera.

Interesujące jest prześledzenie, począwszy od czasu pojawienia się pierwszych komputerów, a skończywszy na współczesności, transformacji wyobrażeń na temat języka asemblera wśród programistów.

Dawno, dawno temu asembler był językiem bez wiedzy o tym, że nie można sprawić, by komputer robił cokolwiek pożytecznego. Stopniowo sytuacja się zmieniła. Pojawiły się wygodniejsze środki komunikacji z komputerem. Ale w przeciwieństwie do innych języków asembler nie umarł, co więcej, nie mógł tego zrobić w zasadzie. Czemu? W poszukiwaniu odpowiedzi postaramy się zrozumieć, czym w ogóle jest język asemblera.

W skrócie, język asemblera jest symboliczną reprezentacją języka maszynowego. Wszystkie procesy w maszynie na najniższym poziomie sprzętowym są sterowane wyłącznie poleceniami (instrukcjami) języka maszynowego. Z tego jasno wynika, że ​​pomimo wspólnej nazwy, język asemblera dla każdego typu komputera jest inny. Dotyczy to również wyglądu programów napisanych w asemblerze oraz idei, których odzwierciedleniem jest ten język.

Bez znajomości asemblera nie da się naprawdę rozwiązać problemów sprzętowych (a co więcej, sprzętowych, takich jak zwiększenie szybkości działania programu).

Programista lub każdy inny użytkownik może korzystać z dowolnych narzędzi wysokiego poziomu, aż do programów do budowania wirtualnych światów, i być może nawet nie podejrzewać, że komputer faktycznie wykonuje polecenia nie w języku, w którym napisany jest jego program, ale ich przekształcona reprezentacja w postaci nudnych i nieciekawych sekwencji poleceń zupełnie innego języka - języka maszynowego. Teraz wyobraźmy sobie, że taki użytkownik ma niestandardowy problem lub po prostu coś poszło nie tak. Na przykład jego program musi współpracować z jakimś nietypowym urządzeniem lub wykonywać inne czynności, które wymagają znajomości zasad działania sprzętu komputerowego. Bez względu na to, jak mądry jest programista, bez względu na to, jak dobry jest język, w którym napisał swój wspaniały program, nie może obejść się bez znajomości asemblera. I nie jest przypadkiem, że prawie wszystkie kompilatory języków wysokiego poziomu zawierają środki łączenia swoich modułów z modułami w asemblerze lub obsługują dostęp do poziomu programowania asemblera.

Oczywiście czas wagonów komputerowych już minął. Jak mówi przysłowie, nie możesz objąć ogromu. Ale jest coś wspólnego, rodzaj fundamentu, na którym zbudowana jest poważna edukacja komputerowa. Jest to wiedza o zasadach działania komputera, jego architekturze i języku asemblera jako odzwierciedlenie i ucieleśnienie tej wiedzy.

Typowy nowoczesny komputer (oparty na i486 lub Pentium) składa się z następujących elementów (Rysunek 1).

Ryż. 1. Komputer i urządzenia peryferyjne

Ryż. 2. Schemat blokowy komputera osobistego

Z rysunku (rys. 1) widać, że komputer składa się z kilku fizycznych urządzeń, z których każde jest połączone z jedną jednostką, zwaną jednostką systemową. Logicznie rzecz biorąc, jest jasne, że pełni rolę jakiegoś urządzenia koordynującego. Zajrzyjmy do jednostki systemowej (nie musisz próbować dostać się do monitora - nie ma tam nic ciekawego, poza tym jest niebezpieczne): otwieramy obudowę i widzimy kilka płyt, bloków, przewodów łączących. Aby zrozumieć ich przeznaczenie, spójrzmy na schemat blokowy typowego komputera (ryc. 2). Nie pretenduje do absolutnej dokładności i ma na celu jedynie pokazanie przeznaczenia, połączenia i typowej kompozycji elementów współczesnego komputera osobistego.

Omówmy schemat na ryc. 2 w nieco niekonwencjonalnym stylu.
To ludzka natura, spotykanie się z czymś nowym, szukanie skojarzeń, które mogą pomóc mu poznać nieznane. Jakie skojarzenia budzi komputer? Dla mnie na przykład komputer często kojarzy się z samą osobą. Czemu?

Osoba tworząca komputer gdzieś w głębi siebie myślała, że ​​tworzy coś podobnego do siebie. Komputer ma narządy percepcji informacji ze świata zewnętrznego - jest to klawiatura, mysz, dyski magnetyczne. Na ryc. 2 te organy znajdują się po prawej stronie szyn systemowych. Komputer ma organy „trawiące” otrzymane informacje - jest to centralny procesor i pamięć RAM. I wreszcie komputer ma narządy mowy, które podają wyniki przetwarzania. To także niektóre z urządzeń po prawej stronie.

Współczesne komputery są oczywiście dalekie od człowieka. Można je porównać do istot wchodzących w interakcję ze światem zewnętrznym na poziomie dużego, ale ograniczonego zestawu nieuwarunkowanych odruchów.
Ten zestaw odruchów tworzy system instrukcji maszynowych. Bez względu na to, jak wysoki poziom komunikujesz się z komputerem, ostatecznie wszystko sprowadza się do nudnej i monotonnej sekwencji instrukcji maszynowych.
Każde polecenie maszyny jest rodzajem bodźca do wzbudzenia takiego lub innego odruchu bezwarunkowego. Reakcja na ten bodziec jest zawsze jednoznaczna i „zapisana” w bloku mikrorozkazów w postaci mikroprogramu. Ten mikroprogram realizuje również działania służące realizacji polecenia maszyny, ale już na poziomie sygnałów dostarczanych do pewnych obwodów logicznych komputera, kontrolując w ten sposób różne podsystemy komputerowe. Jest to tak zwana zasada sterowania mikroprogramem.

Kontynuując analogię z osobą, zauważamy: aby komputer mógł jeść prawidłowo, wynaleziono wiele systemów operacyjnych, kompilatorów dla setek języków programowania itp. Ale wszystkie one są w rzeczywistości tylko daniem, na którym jedzenie (programy) dostarczane jest zgodnie z pewnymi zasadami żołądek (komputer). Tylko żołądek komputera uwielbia dietetyczne, monotonne jedzenie - przekaż mu ustrukturyzowane informacje, w postaci ściśle zorganizowanych ciągów zer i jedynek, których kombinacje tworzą język maszynowy.

Tak więc komputer, będąc zewnętrznie poliglotą, rozumie tylko jeden język - język instrukcji maszynowych. Oczywiście do komunikacji i pracy z komputerem nie jest konieczna znajomość tego języka, ale prawie każdy profesjonalny programista prędzej czy później staje przed koniecznością jego opanowania. Na szczęście programista nie musi próbować dociekać znaczenia różnych kombinacji liczb binarnych, ponieważ już w latach 50-tych programiści zaczęli używać do programowania symbolicznego odpowiednika języka maszynowego, który nazwano językiem asemblerowym. Język ten dokładnie odzwierciedla wszystkie cechy języka maszynowego. Dlatego, w przeciwieństwie do języków wysokiego poziomu, język asemblerowy jest inny dla każdego typu komputera.

Z powyższego możemy wywnioskować, że skoro język asemblera dla komputera jest „natywny”, tylko w nim można napisać najbardziej wydajny program (pod warunkiem, że jest napisany przez wykwalifikowanego programistę). Tutaj jest jedno małe „ale”: jest to bardzo pracochłonny proces, wymagający dużej uwagi i praktycznego doświadczenia. Dlatego w rzeczywistości asembler pisze głównie programy, które mają zapewnić wydajną pracę ze sprzętem. Czasami krytyczne części programu pod względem czasu wykonania lub zużycia pamięci są zapisywane w asemblerze. Następnie są tworzone w formie podprogramów i łączone z kodem w języku wysokiego poziomu.

Rozpoczęcie nauki języka asemblera dowolnego komputera ma sens dopiero po ustaleniu, jaka część komputera jest widoczna i dostępna do programowania w tym języku. Jest to tzw. model programu komputerowego, którego częścią jest model programu mikroprocesorowego, który zawiera 32 rejestry mniej lub bardziej dostępne dla programisty.

Rejestry te można podzielić na dwie duże grupy:

^16 rejestrów niestandardowych;

16 rejestrów systemowych.

Programy asemblerowe bardzo intensywnie używają rejestrów. Większość rejestrów ma określony cel funkcjonalny.

Jak sama nazwa wskazuje, rejestry użytkownika są wywoływane, ponieważ programista może ich używać podczas pisania swoich programów. Rejestry te obejmują (rys. 3):

Osiem 32-bitowych rejestrów, które mogą być używane przez programistów do przechowywania danych i adresów (zwanych również rejestrami ogólnego przeznaczenia (RON)):

sześć rejestrów segmentowych: cs, ds, ss, es, fs, gs;

rejestry stanu i kontroli:

Flagi rejestrują flagi/flagi;

Rejestr wskaźnika poleceń eip/ip.

Ryż. 3. Rejestry użytkowników mikroprocesorów i486 i Pentium

Dlaczego wiele z tych rejestrów jest wyświetlanych z ukośnikiem? Nie, to nie są różne rejestry - są to części jednego dużego rejestru 32-bitowego. Mogą być używane w programie jako osobne obiekty. Zrobiono to, aby zapewnić operacyjność programów napisanych dla młodszych 16-bitowych modeli mikroprocesorów firmy Intel, począwszy od i8086. Mikroprocesory i486 i Pentium mają głównie rejestry 32-bitowe. Ich liczba, z wyjątkiem rejestrów segmentowych, jest taka sama jak w i8086, ale wymiar jest większy, co odzwierciedlają ich oznaczenia - mają
przedrostek e (rozszerzony).

^ Rejestry ogólnego przeznaczenia
Wszystkie rejestry z tej grupy umożliwiają dostęp do ich „dolnych” części (patrz rys. 3). Patrząc na ten rysunek, zauważ, że 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. Odbywa się to, jak zauważyliśmy powyżej, w celu zapewnienia zgodności z młodszymi 16-bitowymi modelami mikroprocesorów firmy Intel.

Wymieńmy rejestry należące do grupy rejestrów ogólnego przeznaczenia. Ponieważ te rejestry są fizycznie zlokalizowane w mikroprocesorze wewnątrz jednostki arytmetyczno-logicznej (ALU), nazywane są również rejestrami ALU:

eax/ax/ah/al (Rejestr akumulatorów) - akumulator.
Służy do przechowywania danych pośrednich. W niektórych poleceniach wymagane jest użycie tego rejestru;

ebx/bx/bh/bl (rejestr bazowy) - rejestr bazowy.
Używany do przechowywania adresu bazowego jakiegoś obiektu w pamięci;

ecx/cx/ch/cl (rejestr licznika) - rejestr licznika.
Jest używany w poleceniach, które wykonują pewne powtarzalne czynności. Jego użycie jest często ukryte i ukryte w algorytmie odpowiedniego polecenia.
Na przykład polecenie organizacji pętli, oprócz przekazania sterowania do polecenia znajdującego się pod określonym adresem, analizuje i dekrementuje wartość rejestru ecx/cx o jeden;

edx/dx/dh/dl (Rejestr danych) - rejestr danych.
Podobnie jak rejestr eax/ax/ah/al przechowuje dane pośrednie. Niektóre polecenia wymagają jego użycia; w przypadku niektórych poleceń dzieje się to niejawnie.

Następujące dwa rejestry służą do obsługi tzw. operacji łańcuchowych, czyli operacji, które sekwencyjnie przetwarzają łańcuchy elementów, z których każdy może mieć długość 32, 16 lub 8 bitów:

esi/si (Rejestr indeksu źródłowego) - indeks źródłowy.
Ten rejestr w operacjach łańcuchowych zawiera aktualny adres elementu w łańcuchu źródłowym;

edi/di (rejestr indeksu przeznaczenia) - indeks odbiorcy (odbiorcy).
Ten rejestr w operacjach łańcuchowych zawiera aktualny adres w łańcuchu docelowym.

W architekturze mikroprocesora na poziomie sprzętu i oprogramowania obsługiwana jest taka struktura danych jak stos. Aby pracować ze stosem w zestawie instrukcji mikroprocesora, jest komendy specjalne, a w modelu oprogramowania mikroprocesorowego są do tego specjalne rejestry:

esp/sp (Rejestr wskaźnika stosu) - rejestr wskaźnika stosu.
Zawiera wskaźnik do szczytu stosu w bieżącym segmencie stosu.

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

Stos to obszar programu do tymczasowego przechowywania dowolnych danych. Oczywiście dane mogą być również przechowywane w segmencie danych, ale w tym przypadku dla każdej tymczasowo przechowywanej danych należy utworzyć oddzielną nazwaną komórkę pamięci, co zwiększa rozmiar programu i liczbę używanych nazw. Wygoda stosu polega na tym, że jego obszar jest ponownie używany, a przechowywanie danych na stosie i pobieranie ich stamtąd odbywa się za pomocą wydajnych poleceń push i pop bez określania jakichkolwiek nazw.
Stos jest tradycyjnie używany, na przykład, do przechowywania zawartości rejestrów używanych przez program przed wywołaniem podprogramu, który z kolei użyje rejestrów procesora „do własnych celów”. Oryginalna zawartość rejestrów wycieka ze stosu po powrocie z podprogramu. Inną powszechną techniką jest przekazywanie wymaganych parametrów do podprogramu przez stos. Podprogram, wiedząc w jakiej kolejności są umieszczane parametry na stosie, może je stamtąd pobrać i wykorzystać w swoim wykonaniu. Charakterystyczną cechą stosu jest specyficzna kolejność próbkowania zawartych w nim danych: w dowolnym momencie na stosie dostępny jest tylko górny element, tj. ostatni element załadowany na stos. Zdejmowanie górnego elementu ze stosu udostępnia następny element. Elementy stosu znajdują się w obszarze pamięci przydzielonej dla stosu, zaczynając od dołu stosu (czyli od jego maksymalnego adresu) do kolejno malejących adresów. Adres najwyższego dostępnego elementu jest przechowywany w rejestrze wskaźników stosu SP. Jak każdy inny obszar pamięci programu, stos musi być zawarty w jakimś segmencie lub stanowić osobny segment. W każdym przypadku adres segmentu tego segmentu jest umieszczany w rejestrze stosu segmentu SS. Zatem para rejestrów SS:SP opisuje adres dostępnej komórki stosu: SS przechowuje adres segmentu stosu, a SP przechowuje przesunięcie ostatnich danych przechowywanych na stosie (rys. 4, a). Zwróćmy uwagę na fakt, że w stanie początkowym wskaźnik stosu SP wskazuje komórkę, która leży pod spodem stosu i nie jest w nim uwzględniona.

Rys 4. Organizacja stosu: a - stan początkowy, b - po załadowaniu jednego elementu (w tym przykładzie zawartość rejestru AX), c - po załadowaniu drugiego elementu (zawartość rejestru DS), d - po wyładowaniu jednego element, e - po wyładowaniu dwóch elementów i powrocie do stanu pierwotnego.

Ładowanie na stos odbywa się za pomocą specjalnego polecenia push stack. Ta instrukcja najpierw zmniejsza zawartość wskaźnika stosu o 2, a następnie umieszcza operand pod adresem w SP. Jeśli np. chcemy tymczasowo zapisać zawartość rejestru AX na stosie, powinniśmy wykonać polecenie

Stos przechodzi do stanu pokazanego na ryc. 1.10, ur. Widać, że wskaźnik stosu jest przesuwany w górę o dwa bajty (w kierunku niższych adresów) i pod ten adres zapisywany jest operand określony w poleceniu push. Następujące polecenie do załadowania na stos, na przykład:

przeniesie stos do stanu pokazanego na rys. 1.10,c. Stos będzie teraz zawierał dwa elementy, z dostępem tylko do górnego, wskazywanego przez wskaźnik stosu SP. Jeśli po pewnym czasie musimy przywrócić oryginalną zawartość rejestrów zapisanych na stosie, musimy wykonać ze stosu polecenia pop (pop):

pop DS
pop AX

Jak duży powinien być stos? Zależy to od tego, jak intensywnie jest używany w programie. Jeśli na przykład planujesz przechowywać na stosie tablicę 10 000 bajtów, stos musi mieć co najmniej ten rozmiar. Należy pamiętać, że w niektórych przypadkach stos jest automatycznie wykorzystywany przez system, w szczególności podczas wykonywania polecenia przerwania int 21h. Za pomocą tego polecenia procesor najpierw wkłada adres powrotu na stos, a następnie DOS wkłada tam zawartość rejestrów i inne informacje związane z przerwanym programem. Dlatego nawet jeśli program w ogóle nie korzysta ze stosu, musi on nadal być obecny w programie i mieć rozmiar co najmniej kilkudziesięciu słów. W naszym pierwszym przykładzie umieściliśmy 128 słów na stosie, co zdecydowanie wystarczy.

^ Struktura programu montażowego

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

Oświadczenia montażowe są czterech typów:

polecenia lub instrukcje, które są symbolicznym odpowiednikiem instrukcji maszynowych. Podczas procesu translacji instrukcje asemblera są konwertowane na odpowiednie polecenia zestawu instrukcji mikroprocesora;

makropolecenia - zdania tekstu programu, które są zaprojektowane w określony sposób i są zastępowane innymi zdaniami podczas tłumaczenia;

dyrektywy, które mówią kompilatorowi asemblera, aby wykonał jakąś akcję. Dyrektywy nie mają odpowiedników w reprezentacji maszynowej;

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

^ Składnia języka asemblera

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. W tym celu najlepiej jest użyć formalnego opisu składni języka, podobnie jak zasad gramatyki. Najczęstszymi sposobami opisu języka programowania w ten sposób są diagramy składni i rozszerzone formularze Backusa-Naura. W praktyce diagramy składni są wygodniejsze. Na przykład, składnia instrukcji języka asemblera może być opisana za pomocą diagramów składni pokazanych na poniższych rysunkach.

Ryż. 5. Format zdania w asemblerze

Ryż. 6. Dyrektywy formatu

Ryż. 7. Format poleceń i makr

Na tych rysunkach:

nazwa etykiety - identyfikator, którego wartością jest adres pierwszego bajtu zdania kodu źródłowego programu, który oznacza;

name - identyfikator odróżniający tę dyrektywę od innych dyrektyw o tej samej nazwie. W wyniku przetworzenia przez asembler pewnej dyrektywy, pewne cechy mogą być przypisane do tej nazwy;

kod operacji (COP) i dyrektywa to mnemoniczne oznaczenia odpowiedniej instrukcji maszynowej, makroinstrukcji lub dyrektywy translatora;

operandy - części dyrektyw command, makr lub assemblera, oznaczające obiekty, na których wykonywane są operacje. Operandy asemblera są opisywane za pomocą wyrażeń ze stałymi liczbowymi i tekstowymi, etykietami zmiennych i identyfikatorów za pomocą znaków operacji i niektórych słów zastrzeżonych.

^ Jak korzystać z diagramów składniowych? To bardzo proste: wystarczy znaleźć, a następnie podążać ścieżką 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. Podczas pracy z diagramami składni zwracaj uwagę na kierunek obejścia wskazywany przez strzałki, ponieważ wśród ścieżek mogą znajdować się te, którymi można podążać od prawej do lewej. W rzeczywistości diagramy składniowe odzwierciedlają logikę tłumacza podczas analizowania zdań wejściowych programu.

Dozwolone znaki podczas pisania tekstu programów to:

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

Liczby od 0 do 9;

Znaki?, @, $, _, &;

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

Zdania asemblerowe są tworzone z leksemów, które są syntaktycznie nierozłącznymi sekwencjami ważnych symboli językowych, które mają sens dla tłumacza.

Tokeny to:

Identyfikatory to sekwencje prawidłowych znaków używanych 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. Jako znaki możesz używać liter alfabetu łacińskiego, cyfr i niektórych znaków specjalnych - _, ?, $, @. Identyfikator nie może zaczynać się od cyfry. Długość identyfikatora może wynosić do 255 znaków, chociaż tłumacz akceptuje tylko pierwsze 32 znaki i ignoruje resztę. Możesz dostosować długość możliwych identyfikatorów za pomocą opcji wiersz poleceń pom. Ponadto można powiedzieć tłumaczowi, aby rozróżniał wielkie i małe litery lub ignorował ich różnicę (co jest wykonywane domyślnie).

^ Polecenia języka asemblera.

Instrukcje montażu ujawniają możliwość przeniesienia swoich wymagań do komputera, mechanizm przekazywania sterowania w programie (pętle i skoki) dla logiczne porównania i organizacja oprogramowania. Jednak zadania programistyczne rzadko są tak proste. Większość programów zawiera serie pętli, w których kilka instrukcji jest powtarzanych, aż do osiągnięcia określonego wymagania, oraz różne kontrole w celu określenia, które z kilku działań należy wykonać. Niektóre polecenia mogą przekazywać kontrolę, zmieniając normalną sekwencję kroków przez bezpośrednią modyfikację wartości przesunięcia we wskaźniku polecenia. Jak wspomniano wcześniej, istnieją różne polecenia dla różnych procesorów, ale rozważymy kilka niektórych poleceń dla procesorów 80186, 80286 i 80386.

Do opisu stanu flag po wykonaniu określonego polecenia posłużymy się wyborem z tabeli, który odzwierciedla strukturę rejestru flag flag:

Dolny wiersz tej tabeli zawiera wartości flag po wykonaniu polecenia. W takim przypadku stosuje się następujące zapisy:

1 - po wykonaniu polecenia flaga jest ustawiana (równa 1);

0 - po wykonaniu komendy flaga jest resetowana (równa 0);

r - wartość flagi zależy od wyniku polecenia;

Po wykonaniu polecenia flaga jest niezdefiniowana;

spacja - po wykonaniu polecenia flaga nie zmienia się;

Poniższa notacja jest używana do reprezentowania operandów na diagramach składniowych:

r8, r16, r32 - operand w jednym z rejestrów o wielkości bajt, słowo lub podwójne słowo;

m8, m16, m32, m48 - operand w pamięci wielkości bajtów, słowa, podwójnego słowa lub 48 bitów;

i8, i16, i32 - natychmiastowy operand o rozmiarze bajt, słowo lub podwójne słowo;

a8, a16, a32 - adres względny (przesunięcie) w segmencie kodu.

Polecenia (w porządku alfabetycznym):

*Te polecenia są szczegółowo opisane.

DODAJ
(Dodatek)

Dodatek

^ Zarys polecenia:

dodaj miejsce docelowe, źródło

Cel: dodanie dwóch operandów źródłowych i docelowych wymiarów bajtu, słowa lub podwójnego słowa.

Algorytm pracy:

dodaj operandy źródłowe i docelowe;

zapisz wynik dodawania do odbiornika;

ustawić flagi.

Status flag po wykonaniu polecenia:

Aplikacja:
Polecenie add służy do dodawania dwóch operandów całkowitych. Wynik dodawania umieszczany jest pod adresem pierwszego operandu. Jeżeli wynik dodawania wykracza poza granice operandu docelowego (występuje przepełnienie), to należy to wziąć pod uwagę analizując flagę cf i ewentualnie używając polecenia adc. Na przykład dodajmy wartości w rejestrze ax i obszar pamięci ch. Przy dodawaniu należy wziąć pod uwagę możliwość przepełnienia.

Rejestr plus rejestr lub pamięć:

|000000dw|modregr/rm|

Rejestr AX (AL) plus wartość natychmiastowa:

|0000010w|--data--|dane, jeśli w=1|

Rejestr lub pamięć plus wartość natychmiastowa:

|100000sw|mod000r/m|--data--|dane, jeśli BW=01|

POŁĄCZENIE
(POŁĄCZENIE)

Wywołanie procedury lub zadania

^ Zarys polecenia:

Zamiar:

przeniesienie kontroli do procedury bliskiej lub dalekiej z zapisaniem adresu punktu zwrotnego na stosie;

Przełączanie zadań.

Algorytm pracy:
określony przez typ operandu:

Etykieta jest blisko - zawartość wskaźnika polecenia eip / ip jest odkładana na stos i nowa wartość adresu odpowiadająca etykiecie jest ładowana do tego samego rejestru;

Far label - zawartość wskaźnika poleceń eip/ip i cs jest umieszczana na stosie. Następnie nowe wartości adresu odpowiadające dalekiemu znacznikowi są ładowane do tych samych rejestrów;

R16, 32 lub m16, 32 - określają rejestr lub komórkę pamięci zawierającą przesunięcia w bieżącym segmencie instrukcji, do którego przekazywane jest sterowanie. Kiedy kontrola jest przekazywana, zawartość wskaźnika polecenia eip/ip jest odkładana na stos;

Wskaźnik pamięci - określa komórkę pamięci zawierającą 4 lub 6 bajtowy wskaźnik do wywoływanej procedury. Struktura takiego wskaźnika to 2+2 lub 2+4 bajty. Interpretacja takiego wskaźnika zależy od trybu pracy mikroprocesora:

^ Stan flag po wykonaniu polecenia (z wyjątkiem przełączania zadań):

wykonanie polecenia nie wpływa na flagi

Po przełączeniu zadania wartości flag są zmieniane zgodnie z informacją o rejestrze flag w segmencie statusu TSS przełączanego zadania.
Aplikacja:
Polecenie wywołania umożliwia zorganizowanie elastycznego i wielowymiarowego przekazania sterowania do podprogramu przy zachowaniu adresu punktu zwrotnego.

Kod obiektu (cztery formaty):

Adresowanie bezpośrednie w segmencie:

|11101000|disp-niskie|diep-high|

Adresowanie pośrednie w segmencie:

|11111111|mod010r/m|

Adresowanie pośrednie między segmentami:

|11111111|mod011r/m|

Adresowanie bezpośrednie między segmentami:

|10011010|przesunięcie-niskie|przesunięcie-wysokie|seg-niskie|seg-wysokie|

CMP
(porównaj operandy)

Porównanie argumentów

^ Zarys polecenia:

cmp operand1, operand2

Cel: porównanie dwóch argumentów.

Algorytm pracy:

wykonaj odejmowanie (operand1-operand2);

w zależności od wyniku ustaw flagi, nie zmieniaj operandu1 i operandu2 (czyli nie przechowuj wyniku).

Aplikacja:
To polecenie służy do porównywania dwóch operandów przez odejmowanie, podczas gdy operandy nie zmieniają się. Flagi są ustawiane w wyniku wykonania polecenia. Instrukcja cmp jest używana z instrukcjami skoku warunkowego i instrukcją set byte by value setcc.

Kod obiektu (trzy formaty):

Pamięć rejestrowa lub zarejestrowana:

|001110dw|modreg/m|

Wartość natychmiastowa z rejestrem AX (AL):

|0011110w|--data--|data, jeśli w=1|

Wartość natychmiastowa z rejestrem lub pamięcią:

|100000sw|mod111r/m|--data--|dane, jeśli sw=0|

DEC
(DECrement operand o 1)

Operand dekrementacja o jeden

^ Zarys polecenia:

operand dec

Cel: zmniejszenie wartości operandu w pamięci lub rejestrze o 1.

Algorytm pracy:
instrukcja odejmuje 1 od operandu. Status flag po wykonaniu polecenia:

Aplikacja:
Polecenie dec służy do zmniejszania wartości bajtu, słowa, podwójnego słowa w pamięci lub rejestrze o jeden. Zauważ, że polecenie nie wpływa na flagę cf.

Zarejestruj się: |01001reg|

^ Rejestr lub pamięć: |1111111w|mod001r/m|

DIV
(DIVide bez znaku)

Podział niepodpisany

Schemat poleceń:

dzielnik div

Cel: wykonanie operacji dzielenia na dwóch binarnych wartościach bez znaku.

^ Algorytm pracy:
Polecenie wymaga dwóch operandów - dzielnika i dzielnika. Dywidenda jest określona niejawnie, a jej wielkość zależy od wielkości dzielnika, który jest określony w poleceniu:

jeśli dzielnik jest w bajtach, to dywidenda musi znajdować się w rejestrze ax. Po operacji iloraz umieszcza się w al, a resztę w ah;

jeśli dzielnikiem jest słowo, to dywidenda musi znajdować się w parze rejestrów dx:ax, z dolną częścią dywidendy w ax. Po operacji iloraz umieszcza się w ax, a resztę w dx;

jeśli dzielnik jest słowem podwójnym, to dywidenda musi znajdować się w parze rejestrów edx:eax, z dolną częścią dywidendy w eax. Po operacji iloraz umieszcza się w eax, a resztę w edx.

^ Stan flag po wykonaniu polecenia:

Aplikacja:
Polecenie wykonuje całkowite dzielenie operandów, zwracając wynik dzielenia jako iloraz i resztę dzielenia. Podczas wykonywania operacji dzielenia może wystąpić wyjątek: 0 - błąd dzielenia. Taka sytuacja ma miejsce w jednym z dwóch przypadków: dzielnik wynosi 0 lub iloraz jest zbyt duży, aby zmieścić się w rejestrze eax/ax/al.

Kod obiektu:

|1111011w|mod110r/m|

WEWN
(Przerwać)

Wywołanie procedury obsługi przerwań

^ Zarys polecenia:

int numer_przerwania

Cel: wywołanie procedury obsługi przerwań z numerem przerwania określonym przez operand instrukcji.

^ Algorytm pracy:

włóż rejestr flag/flag i adres zwrotny na stos. Podczas pisania adresu zwrotnego najpierw zapisywana jest zawartość rejestru segmentowego cs, a następnie zawartość wskaźnika polecenia eip/ip;

zresetuj flagi if i tf do zera;

przenieś kontrolę do obsługi przerwań o określonym numerze. Mechanizm przekazywania sterowania zależy od trybu pracy mikroprocesora.

^ Stan flag po wykonaniu polecenia:

Aplikacja:
Jak widać ze składni, istnieją dwie formy tego polecenia:

int 3 - ma swój własny kod operacyjny 0cch i zajmuje jeden bajt. Ta okoliczność sprawia, że ​​bardzo wygodne jest używanie w różnych debugerach programowych do ustawiania punktów przerwania przez zastąpienie pierwszego bajtu dowolnej instrukcji. Mikroprocesor, napotykając w sekwencji instrukcji polecenie z kodem 0cch, wywołuje obsługę przerwań o wektorze numer 3, która służy do komunikacji z debugger oprogramowania.

Druga forma instrukcji ma długość dwóch bajtów, kod operacji 0cdh i pozwala zainicjować wywołanie procedury obsługi przerwań z numerem wektora z zakresu 0-255. Jak wspomniano, cechy przekazywania sterowania zależą od trybu pracy mikroprocesora.

Kod obiektu (dwa formaty):

Zarejestruj się: |01000reg|

^ Rejestr lub pamięć: |1111111w|mod000r/m|

JCC
JCXZ/JECXZ
(Skocz, jeśli warunek)

(Skocz, jeśli CX=Zero/ Skocz, jeśli ECX=Zero)

Skocz, jeśli warunek jest spełniony

Skocz, jeśli CX/ECX wynosi zero

^ Zarys polecenia:

etykieta jcc
etykieta jcxz
etykieta jecxz

Cel: przejście w ramach bieżącego segmentu poleceń, w zależności od jakiegoś warunku.

^ Algorytm poleceń (z wyjątkiem jcxz/jecxz):
Sprawdzanie stanu flag w zależności od opcode (odzwierciedla sprawdzany warunek):

jeśli testowany warunek jest prawdziwy, przejdź do komórki wskazanej przez operand;

jeśli sprawdzany warunek jest fałszywy, przekaż kontrolę do następnego polecenia.

Algorytm polecenia jcxz/jecxz:
Sprawdzenie warunku, że zawartość rejestru ecx/cx jest równa zero:

jeśli sprawdzany warunek

Struktury w asemblerze

Tablice, które rozważaliśmy powyżej, to zbiór elementów tego samego typu. Ale często w aplikacjach istnieje potrzeba uwzględnienia pewnego zestawu danych inny rodzaj jako jakiś pojedynczy typ.

Jest to bardzo istotne na przykład w przypadku programów bazodanowych, gdzie konieczne jest powiązanie zbioru danych różnych typów z jednym obiektem.

Na przykład wcześniej przyjrzeliśmy się Listingowi 4, który działał z tablicą elementów trzybajtowych. Z kolei każdy element składał się z dwóch elementów różnego typu: jednobajtowego pola licznika i dwubajtowego pola, które mogło zawierać więcej informacji potrzebnych 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.

Zgodnie z definicją 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 zrobić trzy rzeczy:

    Zapytać się szablon struktury .

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

    Definiować instancja struktury .

    Ten etap polega na inicjalizacji konkretnej zmiennej z predefiniowaną (przy użyciu szablonu) strukturą.

    Zorganizować dostęp do członków struktury .

Bardzo ważne jest, abyś od samego początku zrozumiał, jaka jest między nimi różnica opis struktury w programie i jego definicja.

opisać struktura w programie oznacza jedynie wskazanie jego schematu lub wzoru; pamięć nie jest przydzielona.

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

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

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

Opis szablonu struktury

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

nazwa_struktury STRUC

nazwa_struktury ENDS

Tutaj jest sekwencją dyrektyw opisu danych db, dw, dd, dq oraz dt.

Ich operandy określają wielkość pól i opcjonalnie wartości początkowe. Wartości te prawdopodobnie zainicjują odpowiednie pola, gdy struktura zostanie zdefiniowana.

Jak już zauważyliśmy przy opisie szablonu, 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ę przed miejscem, 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ż pracę ze strukturami na przykładzie modelowania bazy danych pracowników określonego działu.

Dla uproszczenia, aby odejść od problemów konwersji informacji podczas wprowadzania ustalimy, że wszystkie pola są symboliczne.

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

Definiowanie danych o typie struktury

Aby skorzystać ze struktury opisanej przy pomocy szablonu w programie, konieczne jest zdefiniowanie zmiennej o typie tej struktury. Służy do tego następująca składnia:

[nazwa zmiennej] nazwa_struktury

    nazwa zmiennej- identyfikator zmiennej danego typu konstrukcji.

    Podanie nazwy zmiennej jest opcjonalne. Jeśli nie jest określony, obszar pamięci o rozmiarze sumy długości wszystkich elementy konstrukcji.

    lista wartości- lista w nawiasach ostrych Wartości początkowe elementy struktury oddzielone przecinkami.

    Jego zadanie również jest opcjonalne.

    Jeżeli lista jest niekompletna, to wszystkie pola struktury dla danej zmiennej są inicjowane wartościami z szablonu, jeśli występują.

    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śli definiując nową zmienną o typie tej struktury zgadzamy się z wszystkimi wartościami pól w jej szablonie (czyli domyślnie ustawionymi), to wystarczy wpisać nawiasy ostre.

    Na przykład: zwycięski robotnik.

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

Metody struktury

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

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

    adres_wyrażenie- identyfikator zmiennej pewnego typu strukturalnego lub wyrażenie w nawiasach zgodnie z zasadami składni 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.

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 do topór wartości pól z wiekiem. Ponieważ jest mało prawdopodobne, aby wiek osoby pełnosprawnej przekroczył 99 lat, po umieszczeniu zawartości tego pola znaku 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 „mały bajt pod niskim adresem” najwyższa cyfra wieku zostanie umieszczona w glin, a najmłodsi w Ach.

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

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

i jest to możliwe tak:

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

Jak poradzić sobie z rozmiarem i jak zorganizować indeksowanie elementów tablicy?

Podobnie jak inne identyfikatory zdefiniowane w programie, translator przypisuje nazwę typu struktury i nazwę zmiennej z typem struktury atrybutem typu. Wartością tego atrybutu jest rozmiar w bajtach zajmowany przez pola tej struktury. Możesz wyodrębnić tę wartość za pomocą operatora rodzaj.

Gdy rozmiar instancji struktury stanie się znany, organizowanie indeksowania w tablicy struktur nie jest szczególnie trudne.

Na przykład:

Jak skopiować pole z jednej struktury do odpowiadającego pola innej struktury? Albo jak skopiować całą konstrukcję? 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 pracownik)*2 ;si=77*2

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

Wydaje mi się, że kunszt 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 jedzenia. A jeśli się to uda, to moralna satysfakcja jest nie mniejsza, a może więcej, niż ze wspaniałej kolacji u gospodyni. Wydaje mi się, że stopień tej satysfakcji zależy od stopnia zamiłowania do wykonywanego zawodu.

Z drugiej strony postęp w rozwoju oprogramowania i sprzętu nieco odpręża programistę i dość często dochodzi do sytuacji podobnej do znanego przysłowia o locie i słoniu - do rozwiązania jakiegoś drobnego problemu używa się ciężkich narzędzi. zaangażowanych, których skuteczność w ogólnym przypadku ma znaczenie tylko przy realizacji stosunkowo dużych projektów.

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

Temat 1.4 Mnemotechnika asemblera. Struktura i formaty poleceń. Rodzaje adresowania. Zestaw instrukcji 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

1ję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. Z tego jasno wynika, że ​​pomimo wspó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 zbiór zdań językowych, z których każdy zajmuje oddzielny wiersz kodu programu.

Oświadczenia montażowe są czterech typów:

1) polecenia lub instrukcje które są symbolicznym odpowiednikiem poleceń maszynowych. Podczas procesu translacji instrukcje asemblera są konwertowane na odpowiednie polecenia zestawu instrukcji mikroprocesora;

2) makra -zdania tekstu programu, które są w pewien sposób sformalizowane, zastępowane są w trakcie emisji innymi zdaniami;

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

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

­ Struktura programu montażowego. składnia asemblera.

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. W tym celu najlepiej jest użyć formalnego opisu składni języka, podobnie jak zasad gramatyki. Najczęstsze sposoby opisania takiego języka programowania - diagramy składni oraz rozszerzone formy Backusa-Naura. Wygodniejszy w praktycznym użyciu diagramy składni. Na przykład, składnia instrukcji języka asemblerowego może być opisana za pomocą diagramów składni pokazanych 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 rysunkach:

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

­ Nazwa -identyfikator, który odróżnia tę dyrektywę od innych dyrektyw o tej samej nazwie. W wyniku przetworzenia przez asembler pewnej dyrektywy, pewne cechy mogą być przypisane do tej nazwy;

­ kod operacji (COP) i dyrektywa - są to symbole mnemoniczne dla odpowiedniej instrukcji maszynowej, makroinstrukcji lub dyrektywy kompilatora;

­ operandy -części polecenia, makra lub dyrektywy asemblera, oznaczające obiekty, na których wykonywane są akcje. Operandy asemblera są opisywane za pomocą wyrażeń ze stałymi liczbowymi i tekstowymi, etykietami zmiennych i identyfikatorów za pomocą znaków operacji i niektórych słów zastrzeżonych.

Pomoc w diagramach składni znajdź, a następnie przemierz ścieżkę 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 programów 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 zanim 9 ;

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

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

Zdania asemblera są tworzone z tokeny, które są syntaktycznie nierozłącznymi sekwencjami prawidłowych znaków językowych, które mają sens dla tłumacza.

tokeny 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 - sekwencje znaków ujęte w pojedyncze lub podwójne cudzysłowy;

3) liczby całkowite w jednym z następujących systemów liczbowych : binarny, dziesiętny, szesnastkowy. Identyfikacja numerów podczas zapisywania ich w programach asemblera odbywa się według pewnych zasad:

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 konieczne jest, po wpisaniu zer i jedynek wchodzących w ich skład, umieścić łacinę „ b”, na przykład 10010101 b.

5) Liczby szesnastkowe mają więcej konwencji w notacji:

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ą składać się z samych cyfr 0...9 (np. 190845) lub zaczynać się od litery alfabetu łacińskiego (np. ef15). Aby "wyjaśnić" tłumaczowi, że dany leksem nie jest liczbą dziesiętną ani identyfikatorem, programista musi specjalnie przydzielić 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, jest poprzedzona wiodącym zerem: 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 mają wpływ instrukcje lub dyrektywy, lub są to obiekty, które definiują lub udoskonalają działanie instrukcji lub dyrektyw.

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

­ operandy stałe lub natychmiastowe;

­ operandy adresowe;

­ przesunięte operandy;

licznik adresów;

­ operand rejestru;

­ argumenty bazowe i indeksowe;

­ operandy strukturalne;

dokumentacja.

Argumenty to elementarne komponenty, które tworzą część instrukcji maszynowej, oznaczające 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 rozpatrywane jako całość. Wynikiem oceny wyrażenia może być adres jakiejś komórki pamięci lub pewna wartość stała (bezwzględna).

­ 3 Rodzaje instrukcji asemblera

Wymieńmy możliwe typy oświadczenia asemblera oraz syntaktyczne zasady tworzenia wyrażeń asemblera:

­ operatory arytmetyczne;

­ operatorzy zmian;

­ operatory porównania;

­ operatory logiczne;

­ operator indeksu;

­ operator zmiany typu;

­ operator redefinicji segmentu;

­ operator nazewnictwa typu struktury;

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

­ operator get wyrażenie offset.

1 Dyrektywy montażowe

­ Dyrektywy asemblera to:

1) Dyrektywy segmentacyjne. W trakcie poprzedniej dyskusji odkryliśmy wszystkie podstawowe zasady pisania instrukcji i operandów w programie asemblerowym. Pytanie, jak prawidłowo sformatować sekwencję poleceń, aby tłumacz mógł je przetwarzać, a mikroprocesor mógł je wykonywać, pozostaje otwarte.

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 polecenia 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 - Opis składniowy 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. Polega ona na ujednoliceniu 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 przeznaczone są do implementacji różnych opcji takiej unii.

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

­ ogólne dyrektywy sterujące listowaniem;

­ dyrektywy wyjściowe zawierające listę plików;

­ dyrektywy wyjściowe dla warunkowych bloków montażowych;

­ dyrektywy wyjściowe do listy makr;

­ dyrektywy do wyświetlania informacji o odsyłaczach na liście;

­ dyrektywy dotyczące zmiany formatu aukcji.

2 Zestaw instrukcji procesora

Zestaw instrukcji procesora pokazano na rysunku 14.

Rozważ główne grupy poleceń.

­ Rysunek 14 - Klasyfikacja instrukcji montażu

Polecenia to:

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

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

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

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

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

W innych procesorach oprócz instrukcji MOV istnieje kilka innych poleceń wykonujących wymienione funkcje. Polecenia przesyłania danych obejmują również polecenia wymiany informacji (ich oznaczenie oparte jest na słowie Wymieniać się ). Możliwe jest zapewnienie wymiany 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:

­ komendy do operacji na punkcie stałym (dodawanie, odejmowanie, mnożenie, dzielenie);

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

­ polecenia czyszczenia;

­ polecenia inkrementacji i dekrementacji;

­ polecenie porównania.

3 Instrukcje stałoprzecinkowe działają normalnie na kodach w rejestrach procesora lub pamięci kody binarne. Instrukcje zmiennoprzecinkowe (przecinkowe) używają formatu reprezentacji liczbowej z wykładnikiem i mantysą (zwykle te liczby zajmują dwie kolejne lokacje w pamięci). W nowoczesnym potężne procesory zestaw instrukcji zmiennoprzecinkowych nie jest ograniczony 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 potrzebnych w przetwarzaniu dźwięku i obrazu.

4 Polecenia Clear mają na celu zapisanie kodu zerowego do rejestru lub komórki pamięci. Polecenia te można zastąpić instrukcjami transferu kodu zerowego, ale specjalne instrukcje kasujące są zwykle szybsze niż instrukcje transferu.

5 Polecenia zwiększania (zwiększania o jeden) i zmniejszania

(obniżki o jeden) są również bardzo wygodne. Zasadniczo można je zastąpić instrukcjami dodawania lub odejmowania, ale inkrementacja i dekrementacja są szybsze niż dodawanie i odejmowanie. Te instrukcje wymagają jednego operandu wejściowego, który jest również operandem wyjściowym.

6 Instrukcja Compare służy do porównywania dwóch argumentów wejściowych. W rzeczywistości oblicza różnicę tych dwóch operandów, ale nie tworzy operandu wyjściowego, a jedynie zmienia bity w rejestrze stanu procesora na podstawie wyniku tego odejmowania. Instrukcja następująca po instrukcji porównania (zwykle instrukcja skoku) przeanalizuje bity w rejestrze statusu procesora i wykona działania na podstawie ich wartości. Niektóre procesory dostarczają instrukcje do porównywania łańcuchów 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 pojedynczych bitów. W tym różnią się od poleceń arytmetycznych. Polecenia logiczne wykonują następujące podstawowe operacje:

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

­ przesunięcia logiczne, arytmetyczne i cykliczne;

­ sprawdzanie bitów i operandów;

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

Instrukcje logiczne umożliwiają obliczanie bit po bicie podstawowych funkcji logicznych na podstawie dwóch operandów wejściowych. Dodatkowo operacja AND służy do wymuszenia kasowania danych bitów (jednym z operandów jest kod maski, w którym bity wymagające kasowania są ustawione na zero). Operacja OR służy do wymuszenia ustawienia bitów (jako jeden z operandów używany jest kod maski, w którym bity wymagające ustawienia na jeden są równe jedynce). Operacja XOR służy do odwracania podanych bitów (jako jeden z operandów używany jest kod maski, w którym bity do odwrócenia są ustawione na jeden). Instrukcje wymagają dwóch argumentów wejściowych i tworzą jeden argument wyjściowy.

8 Polecenia przesunięcia umożliwiają przesuwanie kodu operandu bit po bicie w prawo (w kierunku niższych bitów) lub w lewo (w kierunku wyższych bitów). Typ przesunięcia (boolean, 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 stara wartość najbardziej znaczącego bit zostanie zapisany gdzieś (przy przesunięciu w lewo) lub najmniej znaczący bit (przy przesunięciu w prawo). Przesunięcia obrotowe umożliwiają przesuwanie bitów kodu operandu w okręgu (zgodnie z ruchem wskazówek zegara przy przesuwaniu w prawo lub przeciwnie do ruchu wskazówek zegara przy przesuwaniu w lewo). W takim przypadku pierścień zmiany biegów może, ale nie musi zawierać flagi przeniesienia. Bit flagi przeniesienia (jeśli jest używany) jest ustawiony na najbardziej znaczący bit dla obrotu w lewo i najmniej znaczący bit dla obrotu w prawo. Odpowiednio, wartość bitu flagi przeniesienia zostanie przepisana do najmniej znaczącego bitu przy lewym przesunięciu cyklicznym i do najbardziej znaczącego bitu przy prawym przesunięciu cyklicznym.

9 Polecenia skoku. Polecenia skoku mają na celu organizowanie wszelkiego rodzaju pętli, rozgałęzień, wywołań podprogramów itp., to znaczy zakłócają sekwencyjny przepływ programu. Instrukcje te zapisują nową wartość do rejestru licznika instrukcji i tym samym powodują, że procesor przeskakuje nie do następnej instrukcji w kolejności, ale do dowolnej innej instrukcji w pamięci programu. Niektóre komendy skoku pozwalają cofnąć się do punktu, z którego wykonano skok, a inne nie. Jeśli podano zwrot, bieżące parametry procesora są przechowywane na stosie. Jeśli nie zostanie podany zwrot, bieżące parametry procesora nie zostaną zapisane.

Polecenia skoku bez cofania są podzielone na dwie grupy:

­ komendy skoków bezwarunkowych;

­ instrukcje skoku warunkowego.

Te polecenia używają słów Gałąź (gałąź) i Skok (skok).

Bezwarunkowe polecenia skoku powodują skok do nowy adres nieważne co. Mogą spowodować przejście do określona wartość offset (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.

Polecenia skoku warunkowego nie zawsze powodują skok, ale tylko wtedy, gdy spełnione są określone warunki. Takimi warunkami są zazwyczaj wartości 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:

­ skok, jeśli jest równy zero;

­ skok, jeśli niezerowe;

­ skacz, jeśli jest przepełnienie;

­ skacz, jeśli nie ma przelewu;

­ skok, jeśli jest większy od zera;

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

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

W szczególności do sprawdzania warunków rozgałęzień używana jest instrukcja porównania (CMP), która poprzedza instrukcję skoku warunkowego (lub nawet kilka instrukcji skoku warunkowego). Ale flagi można ustawić za pomocą dowolnego innego polecenia, takiego jak polecenie przesyłania danych, dowolne polecenie arytmetyczne lub logiczne. Zwróć uwagę, że same polecenia skoku nie zmieniają flag, co pozwala po prostu umieścić kilka poleceń skoku jedna po drugiej.

Polecenia przerwań zajmują szczególne miejsce wśród poleceń skoku z powrotem. Te instrukcje wymagają numeru przerwania (adresu wektora) jako argumentu wejściowego.

Wniosek:

Język asemblera 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 zbiór zdań językowych, z których każdy zajmuje oddzielny wiersz kodu programu. Instrukcje asemblera są czterech typów: polecenia lub instrukcje, makra, dyrektywy, wiersze komentarza.

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

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

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

­ Pytania testowe:

1 Czym jest język asemblera?

2 Jakich symboli można użyć do pisania poleceń w asemblerze?

3 Czym są etykiety i jaki jest ich cel?

4 Wyjaśnij strukturę instrukcji montażu.

5 Wymień 4 typy instrukcji asemblera.

Kurs pracy

Temat "Programowanie systemu"

Temat nr 4: „Rozwiązywanie problemów związanych z procedurami”

Opcja 2

UNIWERSYTET PAŃSTWOWY WSCHODNIOSYBERYJSKI

TECHNOLOGIA I ZARZĄDZANIE

____________________________________________________________________

KOLEGIUM TECHNOLOGICZNE

ĆWICZENIE

za pracę semestralną

Dyscyplina:
Temat: Rozwiązywanie problemów dla procedur
Artyści: Glavinskaya Arina Aleksandrovna
Kierownik: Sesegma Wiktorowna Dambajewa
Krótkie podsumowanie pracy: badanie podprogramów w języku asemblera,
rozwiązywanie problemów za pomocą podprogramów
1. Część teoretyczna: Podstawowe informacje o asemblerze (zestaw
poleceń itp.), Organizacja podprogramów, Sposoby przekazywania parametrów
w podprogramach
2. Część praktyczna: Opracuj dwa podprogramy, z których jeden zamienia daną literę na wielką (w tym na litery rosyjskie), a drugi zamienia literę na małe.
konwertuje dowolną podaną literę na wielką, a druga konwertuje literę na małą.
konwertuje literę na małe litery.
Harmonogramy projektów zgodnie z harmonogramem:
1. Część teoretyczna - 30% do 7 tygodnia.
2. Część praktyczna - 70% na 11 tygodni.
3. Ochrona - 100% do 14 tygodni.
Wymagania projektowe:
1. Rozliczenie i wyjaśnienie projektu kursu należy złożyć w terminie:
kopie elektroniczne i papierowe.
2. Objętość raportu musi wynosić co najmniej 20 stron maszynopisu, bez załączników.
3. RPP jest sporządzany zgodnie z GOST 7.32-91 i podpisany przez kierownika.

Kierownik pracy __________________

Wykonawca __________________

Data wydania " 26 " Wrzesień 2017 G.


Wstęp. 2

1.1 Podstawowe informacje o asemblerze. 3

1.1.1 Zestaw poleceń. cztery

1.2 Organizacja podprogramów w asemblerze. cztery

1.3 Metody przekazywania parametrów w podprogramach. 6

1.3.1 Przekazywanie parametrów przez rejestry. 6

1.3.2 Przekazywanie parametrów przez stos. 7

2 CZĘŚĆ PRAKTYCZNA.. 9

2.1 Stwierdzenie problemu. 9

2.2 Opis rozwiązania problemu. 9

2.3 Testowanie programu. 7

Wniosek. osiem

Referencje.. 9


Wstęp

Powszechnie wiadomo, że programowanie w asemblerze jest trudne. Jak wiesz, jest teraz wiele różnych języków wysoki poziom, które pozwalają poświęcić znacznie mniej wysiłku podczas pisania programów. Oczywiście pojawia się pytanie, kiedy programista może potrzebować używać asemblera podczas pisania programów. Obecnie istnieją dwa obszary, w których użycie asemblera jest uzasadnione, a często konieczne.

Po pierwsze są to tzw. programy systemowe zależne od maszyny, które zwykle sterują różne urządzenia komputer (takie programy nazywane są sterownikami). W tych programy systemowe stosowane są specjalne instrukcje maszynowe, które nie muszą być używane w zwykłym (lub, jak mówią, stosowany) programy. Polecenia te są niemożliwe lub bardzo trudne do określenia w języku wysokiego poziomu.

Drugi obszar zastosowania Assemblera związany jest z optymalizacją wykonania programu. Bardzo często programy tłumaczące (kompilatory) z języków wysokiego poziomu wytwarzają bardzo nieefektywny program w języku maszynowym. Dotyczy to zwykle programów o charakterze obliczeniowym, w których przez większość czasu wykonywana jest bardzo mała (około 3-5%) część programu (pętla główna). Do rozwiązania tego problemu można wykorzystać tzw. wielojęzyczne systemy programowania, które pozwalają na pisanie części programu w języku różne języki. Zwykle główna część programu jest napisana w języku programowania wysokiego poziomu (Fortran, Pascal, C itp.), a sekcje, w których czas ma krytyczne znaczenie, są napisane w asemblerze. W takim przypadku prędkość całego programu może znacznie wzrosnąć. Jest to często jedyny sposób na uzyskanie przez program wyników w rozsądnym czasie.

Celem tego kursu jest zdobycie praktycznych umiejętności programowania w języku asemblerowym.

Zadania robocze:

1. Zapoznanie się z podstawowymi informacjami o języku asemblera (struktura i komponenty programu w asemblerze, format poleceń, organizacja podprogramów itp.);

2. Zbadanie typów operacji na bitach, formatu i logiki poleceń logicznych asemblera;

3. Rozwiąż indywidualny problem dotyczący użycia podprogramów w asemblerze;

4. Sformułuj wnioski dotyczące wykonanej pracy.

1 SEKCJA TEORETYCZNA

Podstawy asemblera

Asembler to język programowania niskiego poziomu, który jest formatem do pisania instrukcji maszynowych, wygodnym dla ludzkiej percepcji.

Polecenia języka asemblerowego odpowiadają poleceniom procesora jeden do jednego i faktycznie reprezentują wygodną symboliczną formę notacji (kod mnemoniczny) poleceń i ich argumentów. Język asemblera zapewnia również podstawowe abstrakcje programistyczne: łączenie części programu i danych poprzez etykiety z nazwami symbolicznymi i dyrektywami.

Dyrektywy asemblera pozwalają na włączenie bloków danych (opisanych wprost lub odczytanych z pliku) do programu; powtarzać pewien fragment określoną liczbę razy; skompiluj fragment zgodnie z warunkiem; ustaw adres wykonania fragmentu, zmień wartości etykiet podczas kompilacji; używać definicji makr z parametrami itp.

Zalety i wady

Minimalna ilość nadmiarowego kodu (użycie mniejszej liczby poleceń i dostępów do pamięci). W konsekwencji - większa prędkość i mniejszy rozmiar programu;

Duże ilości kodu duża liczba dodatkowe małe zadania;

Słaba czytelność kodu, trudność obsługi (debugowanie, dodawanie funkcji);

· trudność we wdrażaniu paradygmatów programowania i wszelkich innych nieco skomplikowanych konwencji, złożoność wspólnego rozwoju;

Mniej dostępnych bibliotek, ich niska kompatybilność;

· bezpośredni dostęp do sprzętu: porty wejścia-wyjścia, specjalne rejestry procesora;

Maksymalne dopasowanie do pożądana platforma(korzystanie ze specjalnych instrukcji, właściwości techniczne"gruczoł");

· brak możliwości przenoszenia na inne platformy (z wyjątkiem kompatybilnych z binarnymi).

Oprócz instrukcji program może zawierać dyrektywy: polecenia, które nie są tłumaczone bezpośrednio na instrukcje maszynowe, ale kontrolują działanie kompilatora. Ich zestaw i składnia znacznie się różnią i zależą nie od platformy sprzętowej, ale od użytego kompilatora (co daje początek dialektom języków należących do tej samej rodziny architektur). Jako zbiór dyrektyw możemy wyróżnić:

Definicja danych (stałych i zmiennych);

zarządzanie organizacją programu w pamięci i parametrami pliku wyjściowego;

ustawienie trybu kompilatora;

Wszelkiego rodzaju abstrakcje (tj. elementy języków wysokiego poziomu) - od projektowania procedur i funkcji (w celu uproszczenia implementacji paradygmatu programowania proceduralnego) po struktury warunkowe i pętle (dla paradygmatu programowanie strukturalne);

makra.

Zestaw poleceń

Typowe instrukcje języka asemblera to:

Polecenia przesyłania danych (mov itp.)

Polecenia arytmetyczne (add, sub, imul itp.)

Operacje logiczne i bitowe (lub i, xor, shr itp.)

Komendy do zarządzania wykonaniem programu (jmp, loop, ret, itp.)

Polecenia wywołania przerwań (czasami nazywane poleceniami sterującymi): int

Polecenia I/O do portów (wejście, wyjście)

Mikrokontrolery i mikrokomputery charakteryzują się również poleceniami, które wykonują sprawdzenia i przejścia według warunków, na przykład:

· jne - skok jeśli nie jest równy;

· jge - skok, jeśli jest większy lub równy .

DZWON

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