Асемблерният език на командата. Накратко за структурата на езика

Курсова работа

В дисциплината "Системно програмиране"

Тема номер 4: „Решаване на задачи за процедури“

Вариант 2

ИЗТОЧЕН СИБИРСКИ ДЪРЖАВЕН УНИВЕРСИТЕТ

ТЕХНОЛОГИЯ И КОНТРОЛ

____________________________________________________________________

ТЕХНОЛОГИЧЕН КОЛЕДЖ

ЗАДАЧАТА

за курсова работа

Дисциплина:
Тема: Решаване на проблеми за процедури
Изпълнител (и): Главинская Арина Александровна
Ръководител: Дамбаева Сесегма Викторовна
Резюмето на работата: изучаване на рутините на асемблерен език,
решаване на проблеми с помощта на подпрограми
1. Теоретична част: Основна информация за езика на събранието (комплект
команди и др.), Организиране на подпрограми, Методи за предаване на параметри
в подпрограмите
2. Практическа част: Разработете две подпрограми, едната от които преобразува дадена буква в главни (включително за руски букви), а другата преобразува буква в малка буква.
преобразува всяка дадена буква в главна буква, а другата преобразува буквата в малка буква.
преобразува буква в малка буква.
Срокове на проекта по график:
1. Теоретична част - 30% за 7 седмици.
2. Практическа част - 70% до 11 седмици.
3. Защита - 100% до 14 седмица.
Изисквания за регистрация:
1. Споразумението и обяснителната бележка за курсовия проект трябва да бъдат представени в
електронни и хартиени копия.
2. Обемът на доклада трябва да бъде най-малко 20 машинописни страници без прикачените файлове.
3. RPZ се изготвя в съответствие с GOST 7.32-91 и се подписва от ръководителя.

Ръководител работа __________________

Изпълнител __________________

Дата на издаване " 26 " септември 2017 ж.


Въведение. 2

1.1 Основна информация за езика на събранието. 3

1.1.1 Набор от команди. 4

1.2 Организиране на подпрограми на асемблерен език. 4

1.3 Методи за предаване на параметри в подпрограмите. 6

1.3.1 Предаване на параметри през регистри .. 6

1.3.2 Предаване на параметри през стека. 7

2 ПРАКТИЧЕСКИ РАЗДЕЛ 9

2.1 Изложение на проблема. девет

2.2 Описание на решението на проблема. девет

2.3 Тестване на програмата .. 7

Заключение. осем

Препратки .. 9


Въведение

Общоизвестно е, че програмирането в Assembler е трудно. Както знаете, сега има много различни езици. високо нивокоито ви позволяват да изразходвате много по-малко усилия при писане на програми. Естествено възниква въпросът кога може да се наложи програмист да използва Assembler, когато пише програми. В момента има две области, в които използването на асемблерен език е оправдано и често необходимо.

Първо, това са така наречените машинно зависими системни програми, обикновено те контролират различни устройства на компютъра (такива програми се наричат \u200b\u200bдрайвери). Тези системни програми използват специални машинни инструкции, които не е необходимо да се използват в обикновени (или, както се казва приложени) програми. Тези команди са невъзможни или трудни за дефиниране на език от високо ниво.

Втората област на използване на Assembler е свързана с оптимизиране на изпълнението на програмата. Много често програмите за превод (компилатори) от езици на високо ниво създават много неефективна програма за машинен език. Това обикновено се отнася до програми от изчислителен характер, при които много малка (около 3-5%) част от програмата (основният цикъл) се изпълнява през повечето време. За да се реши този проблем, могат да се използват така наречените системи за многоезично програмиране, които ви позволяват да пишете части от програмата на различни езици. Обикновено основната част от програмата е написана на език за програмиране на високо ниво (Fortran, Pascal, C и др.), А критичните за времето раздели на програмата са написани в Assembler. В този случай скоростта на цялата програма може да бъде значително увеличена. Това често е единственият начин да накарате програмата да постигне резултат за разумен период от време.

Целта на тази курсова работа е да се получат практически умения за програмиране на асемблерен език.

Работни задачи:

1. Научете основна информация за езика на Асемблер (структура и компоненти на програма Асемблер, команден формат, организация на подпрограми и др.);

2. Да проучи видовете битови операции, формата и логиката на логическите инструкции на Асемблера;

3. Решаване на индивидуален проблем с използването на подпрограми в Assembler;

4 .. Формулирайте заключение за свършената работа.

1 ТЕОРЕТИЧЕН РАЗДЕЛ

Разбиране на езика на събранието

Assembler е език за програмиране на ниско ниво, който е четим от човека формат за писане на машинни инструкции.

Инструкциите на асемблерния език съответстват едно към едно с инструкциите на процесора и всъщност представляват удобна символна форма на нотация (мнемоничен код) на команди и техните аргументи. Също така, асемблерният език предоставя основни софтуерни абстракции: свързване на части от програмата и данни чрез етикети със символни имена и директиви.

Директивите на Assembler ви позволяват да включите блокове с данни (описани изрично или прочетени от файл) в програмата; повторете определен фрагмент определен брой пъти; компилирайте фрагмент условно; задайте адреса на изпълнение на фрагмента, променете стойностите на етикета по време на компилацията; използвайте макроси с параметри и т.н.

Предимства и недостатъци

· Минимално количество излишен код (използвайки по-малко инструкции и достъп до паметта). В резултат на това - по-висока скорост и по-малък размер на програмата;

· Големи количества код, голям брой допълнителни малки задачи;

· Лоша четливост на кода, трудности при поддръжката (отстраняване на грешки, добавяне на функции);

· Трудността при прилагането на парадигми за програмиране и всякакви други по-сложни конвенции, сложността на съвместното развитие;

· По-малко налични библиотеки, тяхната ниска съвместимост;

· Директен достъп до хардуер: входно-изходни портове, специални регистри на процесора;

· Максимално „пригодност“ за желаната платформа (използване на специални инструкции, технически характеристики на „хардуер“);

· Нетолерантност към други платформи (с изключение на двоично съвместими).

В допълнение към инструкциите, една програма може да съдържа директиви: команди, които не се превеждат директно в машинни инструкции, но контролират работата на компилатора. Техният набор и синтаксис варират значително и зависят не от хардуерната платформа, а от използвания компилатор (пораждащи диалекти на езици в рамките на едно и също семейство архитектури). Като набор от директиви могат да се отделят:

· Дефиниция на данни (константи и променливи);

· Управление на организацията на програмата в паметта и параметрите на изходния файл;

· Задаване на режим на работа на компилатора;

· Всички видове абстракции (т.е. елементи на езици на високо ниво) - от проектирането на процедури и функции (за опростяване на прилагането на парадигмата за процедурно програмиране) до условни структури и цикли (за парадигмата на структурираното програмиране);

· Макроси.

Команден набор

Типичните команди на асемблерния език са:

Команди за пренос на данни (mov и др.)

Аритметични команди (add, sub, imul и др.)

Логически и битови операции (или, и, xor, shr и др.)

· Команди за управление на изпълнението на програмата (jmp, loop, ret и др.)

Команди за прекъсване на повикване (понякога наричани команди за управление): int

I / O команди към портове (вход, изход)

За микроконтролери и микрокомпютри също са характерни команди, които извършват проверка и преход по условие, например:

· Jne - преместване, ако не е равно;

· Jge - скок, ако е по-голям или равен.

НАЦИОНАЛЕН УНИВЕРСИТЕТ НА УЗБЕКИСТАН НА ИМЕ СЛЕД МИРЗО УЛУГБЕК

ФАКУЛТЕТ ПО КОМПЮТЪРНИ ТЕХНОЛОГИИ

По темата: Семантичен анализ на EXE файл.

Завършен:

Ташкент 2003.

Предговор.

Асемблерен език и структура на командата.

EXE-файлова структура (семантичен анализ).

COM файлова структура.

Принципът на действие и разпространение на вируса.

Разглобявач.

Програми.

Предговор

Професията на програмистите е невероятна и уникална. В наше време науката и животът не могат да бъдат представени без най-новите технологии. Всичко свързано с човешката дейност не е пълно без компютърни технологии. И това допринася за нейното високо развитие и съвършенство. Въпреки че разработването на персонални компютри започна не толкова отдавна, през това време бяха предприети колосални стъпки в софтуерните продукти и дълго време тези продукти ще бъдат широко използвани. Полето на компютърните знания е избухнало, както и свързаните технологии. Ако не вземете предвид търговската страна, тогава можем да кажем, че в тази област на професионална дейност няма непознати. Мнозина се занимават с разработването на програми не с цел печалба или печалба, а по собствена воля, от хоби. Разбира се, това не трябва да се отразява на качеството на програмата и в този бизнес, така да се каже, "бизнес" има конкуренция и търсене на качествено изпълнение, стабилна работа и отговаряне на всички изисквания на нашето време. Тук също си струва да се отбележи появата на микропроцесори през 60-те години, които дойдоха да заменят голям брой лампи. Има някои видове микропроцесори, които са много различни един от друг. Тези микропроцесори се различават помежду си по битов размер и вградени системни команди. Най-често срещаните са: Intel, IBM, Celeron, AMD и др. Всички тези процесори са свързани с усъвършенстваната архитектура на процесорите Intel. Разпространението на микрокомпютрите предизвика предефиниране на асемблерния език по две основни причини. Първо, програмите, написани на асемблерен език, изискват значително по-малко памет и време за изпълнение. На второ място, познаването на асемблерния език и произтичащия машинен код дава разбиране за архитектурата на машината, което едва ли е възможно при работа на език на високо ниво. Докато повечето софтуерни специалисти се развиват на езици на високо ниво като Pascal, C или Delphi, които са по-лесни за писане, най-мощният и ефективен софтуер е написан изцяло или частично на асемблерен език. Разработени са езици на високо ниво, за да се избегне специалната техничност на конкретни компютри. А асемблерният език от своя страна е предназначен за специфичните специфики на процесора. Следователно, за да се напише програма на асемблерен език за определен компютър, трябва да се знае неговата архитектура. Днес основният софтуерен продукт е EXE файлът. Като се имат предвид положителните страни на това, авторът на програмата може да бъде сигурен в нейната цялост. Но това често не е така. Има и разглобявач. С помощта на разглобявач можете да откриете прекъсвания и програмни кодове. Няма да е трудно за човек, който е добре запознат с асемблерен език, да преработи цялата програма по свой вкус. Може би от тук идва най-неразрешимият проблем - вирусът. Защо хората пишат вирус? Някои хора задават този въпрос с изненада, други с гняв, но въпреки това все още има хора, които се интересуват от този проблем не от гледна точка на причиняване на вреда, а като интерес към системното програмиране. Вирусите пишат по различни причини. Някои хора обичат системните обаждания, други обичат да подобряват познанията си за асемблер. Ще се опитам да очертая всичко това в моята курсова работа. Той също така казва не само за структурата на EXE файла, но и за езика на асемблиране.

^ Асемблерен език.

Интересно е да се проследи от времето на първите компютри до наши дни трансформациите в разбирането на асемблерния език сред програмистите.

Някога асемблерът беше език, без знание на който беше невъзможно да принудиш компютъра да направи нещо полезно. Ситуацията постепенно се промени. Появиха се по-удобни средства за комуникация с компютър. Но, за разлика от други езици, асемблерът не е умрял, освен това по принцип не е могъл да го направи. Защо? В търсене на отговор, нека се опитаме да разберем какво е асемблерният език като цяло.

Накратко, асемблерният език е символично представяне на машинен език. Всички процеси в машината на най-ниското, хардуерно ниво се задвижват само от команди на езика на машината (инструкции). Следователно е ясно, че въпреки общото име, езикът за сглобяване за всеки тип компютър е различен. Това се отнася и за появата на програми, написани на асемблерен език, и идеите, на които този език е отражение.

Невъзможно е наистина да се решат проблеми, свързани с хардуера (или дори, освен това, зависими от хардуера проблеми като подобряване на производителността на програмата), без да се знае асемблер.

Програмист или всеки друг потребител може да използва всякакви средства на високо ниво, до програми за конструиране на виртуални светове и може би дори да не подозира, че всъщност компютърът всъщност не изпълнява командите на езика, на който е написана неговата програма, а трансформираното им представяне под формата на скучно и скучно последователности от команди на съвсем различен език - машина. Сега си представете, че такъв потребител има нестандартен проблем или просто нещо се е объркало. Например, неговата програма трябва да работи с някакво необичайно устройство или да извършва други действия, които изискват познаване на принципите на компютърния хардуер. Колкото и да е умен програмистът, колкото и добър да е езикът, на който е написал прекрасната си програма, той не може без знания на асемблер. И не случайно почти всички компилатори на езици от високо ниво съдържат средства за свързване на своите модули с модули в асемблер или поддържат достъп до програмното ниво на асемблера.

Разбира се, времето на компютърните специалисти отмина. Както се казва, човек не може да схване необятността. Но има нещо общо, един вид основа, върху която се гради всяко сериозно компютърно образование. Това са знания за принципите на компютъра, неговата архитектура и асемблерен език като отражение и въплъщение на това знание.

Типичният съвременен компютър (базиран на i486 или Pentium) се състои от следните компоненти (фиг. 1).

Фигура: 1. Компютър и периферни устройства

Фигура: 2. Блок схема на персонален компютър

От фигурата (Фигура 1) се вижда, че компютърът е съставен от няколко физически устройства, всяко от които е свързано към един блок, наречен системен блок. Логично казано е ясно, че той играе ролята на някакъв вид координиращо устройство. Нека да разгледаме вътрешността на системния блок (няма нужда да се опитваме да влезем вътре в монитора - там няма нищо интересно, освен това е опасно): отваряме кутията и виждаме няколко дъски, блокове, свързващи проводници. За да разберем тяхното функционално предназначение, нека разгледаме блоковата схема на типичен компютър (фиг. 2). Той не се представя за безусловна точност и е предназначен само да покаже целта, взаимовръзката и типичния състав на елементите на съвременен персонален компютър.

Нека обсъдим схемата на фиг. 2 в малко нетрадиционен стил.
Естествено е човек, когато се среща с нещо ново, да търси някакви асоциации, които могат да му помогнат да опознае непознатото. Какви асоциации предизвиква компютърът? За мен например компютърът често се свързва със самия човек. Защо?

Човек, създаващ компютър някъде дълбоко в себе си, си мислеше, че създава нещо подобно на себе си. Компютърът има органи за възприемане на информация от външния свят - това е клавиатура, мишка, магнитни устройства. На фиг. 2 тези органи са разположени вдясно от системните шини. Компютърът има органи, които „смилат“ получената информация - това са централният процесор и паметта с произволен достъп. И накрая, компютърът има органи на речта, които дават резултати от обработката. Това са и някои от устройствата вдясно.

Съвременните компютри, разбира се, са далеч от хората. Те могат да бъдат сравнени със същества, взаимодействащи с външния свят на нивото на голям, но ограничен набор от безусловни рефлекси.
Този набор от рефлекси формира система от машинни инструкции. На каквото и високо ниво да общувате с компютър, в крайна сметка всичко се свежда до скучна и монотонна последователност от машинни инструкции.
Всяка машинна команда е един вид стимул за възбуждане на един или друг безусловен рефлекс. Отговорът на този стимул винаги е еднозначен и е „твърдо свързан“ в блока на микроинструкциите под формата на микропрограма. Тази микропрограма изпълнява действия за изпълнение на машинна команда, но вече на ниво сигнали, подадени към определени логически вериги на компютъра, като по този начин контролира различни подсистеми на компютъра. Това е така нареченият принцип на микропрограмен контрол.

Продължавайки аналогията с хората, отбелязваме: за да може компютърът да се храни правилно, са измислени много операционни системи, компилатори на стотици езици за програмиране и пр. Но всъщност всички те са просто ястие, на което се доставя храна (програми) според определени правила стомах (компютър). Само стомахът на компютъра обича диетичната, монотонна храна - дава му структурирана информация под формата на строго организирани последователности от нули и единици, чиито комбинации съставят машинния език.

По този начин, като външно полиглот, компютърът разбира само един език - езикът на машинните инструкции. Разбира се, за да общувате и работите с компютър, не е необходимо да знаете този език, но почти всеки професионален програмист рано или късно се сблъсква с необходимостта да го научи. За щастие програмистът няма нужда да се опитва да разбере значението на различни комбинации от двоични числа, тъй като през 50-те години програмистите започнаха да използват за програмиране на символен аналог на машинен език, който те наричаха асемблерен език. Този език отразява точно всички характеристики на езика на машината. Ето защо, за разлика от езиците на високо ниво, асемблерният език е различен за всеки тип компютър.

От всичко изброено по-горе можем да заключим, че тъй като асемблерният език е „роден“ за компютър, най-ефективната програма може да бъде написана само в него (при условие че е написана от квалифициран програмист). Тук има едно малко „но“: това е много трудоемък процес, който изисква много внимание и практически опит. Затова в действителност те пишат главно програми в асемблер, които трябва да осигурят ефективна работа с хардуера. Понякога части от програма, които са критични по отношение на времето за изпълнение или консумацията на памет, са написани на асемблерен език. Впоследствие те се форматират като подпрограми и се комбинират с езиковия код на високо ниво.

Има смисъл да започнете да изучавате асемблерния език на всеки компютър само след като разберете коя част от компютъра е оставена видима и достъпна за програмиране на този език. Това е така нареченият софтуерен модел на компютър, част от който е софтуерен модел на микропроцесор, който съдържа 32 регистри по един или друг начин, достъпни за използване от програмист.

Тези регистри могат да бъдат разделени на две големи групи:

^ 16 потребителски регистри;

16 системни регистри.

В асемблерните езикови програми регистрите се използват много интензивно. Повечето от регистрите имат специфична функционалност.

Както подсказва името, потребителските регистри се наричат \u200b\u200bпотребителски регистри, защото програмистът може да ги използва, когато пише своите програми. Тези регистри включват (фиг. 3):

Осем 32-битови регистри, които могат да се използват от програмистите за съхраняване на данни и адреси (наричани още регистри с общо предназначение (RON)):

шест сегментни регистри: cs, ds, ss, es, fs, gs;

регистри за състоянието и контрола:

Флагове регистрират eflags / flags;

Регистърът на указатели за команди eip / ip.

Фигура: 3. Потребителски регистри на i486 и Pentium микропроцесори

Защо много от тези регистри са показани с наклонени разделители? Не, това не са различни регистри - те са части от един голям 32-битов регистър. Те могат да се използват като отделни обекти в програмата. Това се прави, за да се гарантира работоспособността на програми, написани за 16-битови модели от нисък клас на микропроцесори Intel, започвайки с i8086. Микропроцесорите i486 и Pentium имат предимно 32-битови регистри. Техният брой, с изключение на сегментните регистри, е същият като в i8086, но размерът е по-голям, което е отразено в техните обозначения - те имат
префиксът e (Extended).

^ Регистри с общо предназначение
Всички регистри в тази група ви позволяват достъп до техните "долни" части (вижте фиг. 3). Разглеждайки тази фигура, обърнете внимание, че само долните 16 и 8-битови части на тези регистри могат да се използват за самоадресиране. Горните 16 бита на тези регистри не са налични като независими обекти. Това се прави, както отбелязахме по-горе, за съвместимост с по-ниски 16-битови модели на микропроцесори Intel.

Нека изброим регистрите, принадлежащи към групата на регистрите с общо предназначение. Тъй като тези регистри са физически разположени в микропроцесора вътре в аритметичната логическа единица (ALU), те също се наричат \u200b\u200bALU регистри:

eax / ax / ah / al (регистър на акумулатора) - батерия.
Използва се за съхранение на междинни данни. Някои команди изискват този регистър;

ebx / bx / bh / bl (Основен регистър) - основен регистър.
Използва се за съхраняване на основния адрес на някакъв обект в паметта;

ecx / cx / ch / cl (регистър за броене) - брояч.
Използва се в команди, които извършват някои повтарящи се действия. Използването му често е неявно и скрито в алгоритъма на съответната команда.
Например командата за организиране на цикъла, в допълнение към прехвърлянето на управление към командата, намираща се на някакъв адрес, анализира и намалява стойността на регистъра ecx / cx с един;

edx / dx / dh / dl (Data register) - регистър на данните.
Подобно на регистъра eax / ax / ah / al, той съхранява междинни данни. Някои команди изискват използването му; за някои команди това се случва неявно.

Следните два регистъра се използват за поддържане на така наречените верижни операции, тоест операции, които извършват последователна обработка на низове от елементи, всеки от които може да бъде с дължина 32, 16 или 8 бита:

esi / si (регистър на индекса на източника) - индекс на източника.
Този регистър при верижни операции съдържа текущия адрес на елемента във веригата източник;

edi / di (Регистър на целевия индекс) - индекс на получателя (получателя).
Този регистър при верижни операции съдържа текущия адрес в целевата верига.

В микропроцесорна архитектура се поддържа структура от данни като стека на ниво фърмуер. За работа със стека в командната система на микропроцесора има специални команди, а в софтуерния модел на микропроцесора има специални регистри за това:

esp / sp (регистър на указателя на стека) - регистър на указателя на стека.
Съдържа указателя към горната част на стека в текущия сегмент на стека.

ebp / bp (регистър на базовия указател) - регистър на показалеца на основата на рамката на стека.
Проектиран да организира произволен достъп до данни в стека.

Стекът е програмна област за временно съхранение на произволни данни. Разбира се, данните могат да се съхраняват в сегмента от данни, но в този случай за всяка информация, съхранявана за определен период, трябва да се създаде отделна именувана клетка памет, което увеличава размера на програмата и броя на използваните имена. Удобството на стека е, че обхватът му може да се използва многократно и данните се съхраняват в стека и се извличат от там, като се използват ефективните команди за натискане и изскачане, без да се посочват имена.
Стекът традиционно се използва, например, за съхраняване на съдържанието на регистрите, използвани от програма, преди да извика подпрограма, която от своя страна ще използва регистрите на процесора "за свои собствени цели". Оригиналното съдържание на регистрите се изважда от стека при връщане от подпрограмата. Друга често срещана техника е предаването на необходимите параметри през стека на подпрограма. Подпрограмата, знаейки в какъв ред параметрите се изтласкват върху стека, може да ги вземе от там и да ги използва по време на нейното изпълнение. Отличителна черта на стека е един вид извличане на реда на данните, които той съдържа: по всяко време в стека е наличен само най-горният елемент, т.е. последният елемент, избутан върху стека. Разтоварването на горния елемент от стека прави следващия елемент достъпен. Елементите на стека се намират в областта на паметта, разпределена за стека, започвайки от дъното на стека (т.е. от максималния му адрес) при последователно намаляващи адреси. Адресът на горния достъпен елемент се съхранява в регистъра на указателя на стека SP. Както всяка друга област на програмната памет, стекът трябва да влезе в сегмент или да образува отделен сегмент. Във всеки случай адресът на сегмента на този сегмент се поставя в регистъра на сегментите на SS стека. По този начин двойката регистри SS: SP описват адреса на наличната клетка на стека: SS съхранява адреса на сегмента на стека, а SP съхранява изместването на последните данни, съхранени в стека (Фиг. 4, а). Обърнете внимание на факта, че в първоначалното състояние указателят на стека SP сочи към клетка, която лежи под дъното на стека и не е включена в нея.

Фигура 4. Организация на стека: a - начално състояние, b - след зареждане на един елемент (в този пример - съдържанието на регистъра AX), c - след зареждане на втория елемент (съдържание на регистъра DS), d - след разтоварване на един елемент, e - след разтоварване два артикула и се връща в първоначално състояние.

Зареждането в стека се извършва чрез специална команда за стека, натискане (натискане). Тази команда първо намалява съдържанието на указателя на стека с 2 и след това поставя операнда на адреса в SP. Ако например искаме временно да запазим съдържанието на AX регистъра в стека, трябва да изпълним командата

Стекът преминава в състоянието, показано на фиг. 1.10, б. Вижда се, че указателят на стека е изместен с два байта нагоре (към по-ниски адреси) и на този адрес се записва операндът, посочен в командата push Следващото зареждане на командата за стека, например

ще постави стека в състоянието, показано на фиг. 1.10, c. Сега стекът ще съхранява два елемента и ще бъде наличен само най-горният, към който сочи указателят на стека SP. Ако след известно време трябва да възстановим оригиналното съдържание на регистрите, съхранявани в стека, трябва да изпълним командите за изваждане от изскачащия стек (pop):

поп DS
поп AXE

Колко голям трябва да бъде стека? Зависи от това колко силно се използва в програмата. Ако например планирате да съхраните масив от 10 000 байта в стека, тогава стекът трябва да бъде поне с този размер. Трябва да се има предвид, че в някои случаи стекът се използва автоматично от системата, по-специално, когато се изпълни командата за прекъсване int 21h. С тази команда процесорът първо избутва адреса за връщане в стека, а след това DOS изпраща там съдържанието на регистри и друга информация, свързана с прекъснатата програма. Следователно, дори ако програмата изобщо не използва стека, той все още трябва да присъства в програмата и да е с размер поне няколко десетки думи. В първия си пример поставихме 128 думи в стека, което със сигурност е достатъчно.

^ Структурата на програма в сглобяване

Програмата за асемблерен език е колекция от блокове памет, наречени сегменти на паметта. Програмата може да се състои от един или няколко такива блокови сегмента. Всеки сегмент съдържа набор от езикови изречения, всеки от които заема отделен ред от програмен код.

Изреченията за събрание са от четири вида:

команди или инструкции, които са символни аналози на машинни инструкции. В процеса на превод инструкциите на асемблера се преобразуват в съответните команди от набора инструкции на микропроцесора;

макросите са изречения от програмния текст, които се формират по определен начин, които се заменят по време на излъчването с други изречения;

директиви, които инструктират асемблерния преводач да извършва определени действия. Директивите нямат аналог в машинното представяне;

редове за коментари, съдържащи всякакви знаци, включително букви от руската азбука. Коментарите се пренебрегват от преводача.

^ Синтаксис на асемблера

Изреченията, съставляващи програмата, могат да бъдат синтактична конструкция, съответстваща на команда, макрос, директива или коментар. За да може асемблерният преводач да ги разпознае, те трябва да се формират според определени синтактични правила. Най-добрият начин да направите това е да използвате официално описание на синтаксиса на езика, като граматичните правила. Най-често срещаните начини за описание на програмен език по този начин са синтаксисните диаграми и разширените форми на Backus-Naur. За практическа употреба синтаксисните диаграми са по-удобни. Например синтаксисът на изреченията на асемблера може да бъде описан с помощта на синтаксисните диаграми, показани на следващите фигури.

Фигура: 5. Формат на изречението на асемблера

Фигура: 6. Формат на директивите

Фигура: 7. Формат на команди и макроси

На тези фигури:

име на етикет - идентификатор, чиято стойност е адресът на първия байт от изречението на изходния текст на програмата, който той обозначава;

name - идентификатор, който отличава тази директива от други директиви със същото име. В резултат на обработката на асемблерен език на конкретна директива на това име могат да бъдат присвоени определени характеристики;

операционният код (COP) и директивата са мнемонични обозначения на съответната машинна инструкция, макрокоманда или директива на преводача;

операндите са части от инструкция, макрос или асемблерна директива, които обозначават обекти, които трябва да бъдат манипулирани. Операндите на асемблера се описват чрез изрази с числови и текстови константи, етикети и идентификатори на променливи, като се използват операционни знаци и някои запазени думи.

^ Как да използвам синтаксисни диаграми? Това е много просто: просто трябва да намерите и след това да преминете от входа на диаграмата (вляво) към нейния изход (вдясно). Ако такъв път съществува, тогава изречението или конструкцията са синтактично правилни. Ако няма такъв път, тогава компилаторът няма да приеме тази конструкция. Когато работите със синтаксични диаграми, обърнете внимание на посоката на обръщане, посочена със стрелките, тъй като сред пътеките може да има някои, които могат да се следват отдясно наляво. Всъщност синтаксисните диаграми отразяват логиката на преводача при анализиране на входните изречения на програмата.

Разрешените знаци при писане на програмен текст са:

Всички латински букви: A-Z, a-z. В този случай главни и малки букви се считат за еквивалентни;

Числа от 0 до 9;

Признаци?, @, $, _, &;

Сепаратори ,. ()< > { } + / * % ! " " ? \ = # ^.

Изреченията на асемблера се формират от лексеми, които са синтактично неразделни последователности от валидни езикови символи, които имат смисъл за преводач.

Жетоните са:

идентификаторите са последователности от валидни символи, използвани за обозначаване на програмни обекти като опкодове, имена на променливи и имена на етикети. Правилото за писане на идентификатори е следното: идентификаторът може да се състои от един или повече знака. Букви от латинската азбука, цифри и някои специални знаци - _,?, $, @ Могат да се използват като символи. Идентификаторът не може да започва с цифров знак. Дължината на идентификатора може да бъде до 255 знака, въпреки че преводачът приема само първите 32, а останалите игнорира. Дължината на възможните идентификатори може да се регулира с помощта на опцията за команден ред mv. Освен това е възможно да кажете на преводача да прави разлика между главни и малки букви или да игнорира тяхната разлика (което се прави по подразбиране).

^ Асемблерни команди.

Командите на Assembler разкриват възможността за прехвърляне на техните изисквания към компютъра, механизма за прехвърляне на управление в програмата (цикли и скокове) за логически сравнения и организация на програмата. Програмируемите задачи обаче рядко са толкова лесни. Повечето програми съдържат поредица от цикли, в които се повтарят няколко инструкции, докато се постигне определено изискване, и различни проверки, за да се определи кое от няколко действия да се извърши. Някои команди могат да прехвърлят управление чрез промяна на нормалната последователност от стъпки, като директно променят стойността на отместването в командния указател. Както бе споменато по-рано, има различни инструкции за различните процесори, но ще разгледаме редица инструкции за процесорите 80186, 80286 и 80386.

За да опишем състоянието на флаговете след изпълнение на определена команда, ще използваме проба от таблицата, която отразява структурата на регистъра eflags:

Долният ред на тази таблица изброява стойностите на флага след изпълнението на командата. В този случай се използват следните обозначения:

1 - след изпълнение на командата, флагът се задава (равен на 1);

0 - след изпълнение на командата флагът се изчиства (равен на 0);

r - стойността на флага зависи от резултата от командата;

Флагът е неопределен след изпълнение на команда;

интервал - флагът не се променя след изпълнението на командата;

Следните конвенции се използват за представяне на операнди в синтаксисни диаграми:

r8, r16, r32 - операнд на байт, дума или двойна дума в един от регистрите;

m8, m16, m32, m48 - байт, дума, двойна дума или 48 битов операнд за памет;

i8, i16, i32 - непосредствен операнд на байт, дума или двойна дума;

a8, a16, a32 - относителен адрес (отместване) в кодовия сегмент.

Команди (по азбучен ред):

* Тези команди са описани подробно.

ДОБАВЕТЕ
(ДОБАВЯНЕ)

Събиране

^ Командна схема:

добавяне на дестинация, източник

Предназначение: добавяне на два операнда източник и дестинация в байтове, дума или двойна дума.

Работен алгоритъм:

добавете изходния и целевия операнди;

запишете резултата от добавянето в приемника;

задайте знамена.

Състояние на флаговете след изпълнение на команда:

Приложение:
Командата add се използва за добавяне на два целочислени операнда. Резултатът от добавяне се поставя на адреса на първия операнд. Ако резултатът от добавянето е извън границите на операнда на приемника (настъпва препълване), тогава тази ситуация трябва да се вземе предвид, като се анализира флагът cf и след това се използва командата adc. Например, добавете стойностите в ax и ch. Добавянето трябва да отчита възможността за преливане.

Регистрация плюс регистър или памет:

| 000000dw | modregr / rm |

Регистър AX (AL) плюс непосредствена стойност:

| 0000010w | --data-- | данни, ако w \u003d 1 |

Регистър или памет плюс непосредствена стойност:

| 100000sw | mod000r / m | --data-- | данни, ако BW \u003d 01 |

ОБАДИ СЕ
(ОБАДИ СЕ)

Извикване на процедура или задача

^ Командна схема:

Предназначение:

прехвърляне на контрол към близка или отдалечена процедура със съхраняване на адреса на връщащата точка в стека;

превключване на задачи.

Работен алгоритъм:
определя се от вида на операнда:

Близо етикет - съдържанието на командния указател eip / ip се избутва върху стека и новата стойност на адреса, съответстваща на етикета, се зарежда в същия регистър;

Далечен етикет - съдържанието на командните указатели eip / ip и cs се избутва върху стека. Тогава нови адресни стойности, съответстващи на далечния етикет, се зареждат в същите регистри;

R16, 32 или m16, 32 - дефиниране на регистър или местоположение в паметта, съдържащи отмествания в текущия сегмент с инструкции, към който се прехвърля управлението. Когато управлението се прехвърля, съдържанието на командния указател eip / ip се избутва върху стека;

Указател на паметта - Определя място в паметта, съдържащо 4 или 6 байтов указател на извиканата процедура. Структурата на такъв указател е 2 + 2 или 2 + 4 байта. Тълкуването на такъв указател зависи от режима на работа на микропроцесора:

^ Състояние на флаговете след изпълнение на команда (с изключение на превключване на задача):

изпълнението на команди не засяга флаговете

Когато дадена задача е превключена, стойностите на флаговете се променят в съответствие с информацията от регистъра eflags в сегмента на състоянието на TSS на задачата, към която да превключите.
Приложение:
Командата за повикване ви позволява да организирате гъвкаво и многовариантно прехвърляне на контрола към подпрограма, като същевременно запазвате адреса на връщащата точка.

Относно обектния код (четири формата):

Директно адресиране на сегменти:

| 11101000 | disp-low | дълбоко-високо |

Непряко адресиране в сегмент:

| 11111111 | mod010r / m |

Непряко адресиране между сегменти:

| 11111111 | mod011r / m |

Директно адресиране между сегменти:

| 10011010 | офсет-нисък | офсет-висок | сегмент-нисък | сегмент-висок |

CMP
(Операнди на CoMPare)

Сравнение на операндите

^ Командна схема:

cmp операнд1, операнд2

Цел: сравнение на два операнда.

Работен алгоритъм:

извърши изваждане (операнд1-операнд2);

задайте флагове в зависимост от резултата, не променяйте операнд1 и операнд2 (т.е. не съхранявайте резултата).

Приложение:
Тази команда се използва за изваждане на два операнда, без да се променят операндите. Флаговете се задават въз основа на резултатите от изпълнението на командите. Командата cmp се използва с командите за условен клон и байта по команда setcc.

Относно обектния код (три формата):

Регистър или памет с регистър:

| 001110dw | modregr / m |

Непосредствена стойност с регистър AX (AL):

| 0011110w | --data-- | данни, ако w \u003d 1 |

Незабавна стойност с регистър или памет:

| 100000sw | mod111r / m | --data-- | данни, ако sw \u003d 0 |

DEC
(Операнд DECrement от 1)

Намаляване на операнда с един

^ Командна схема:

dec операнд

Цел: намаляване стойността на операнда в паметта или регистъра с 1.

Работен алгоритъм:
командата изважда 1 от операнда. Състояние на флаговете след изпълнение на команда:

Приложение:
Командата dec се използва за намаляване на стойността на байт, дума, двойна дума в паметта или регистрация по един. Имайте предвид обаче, че командата не засяга флага cf.

Регистър: | 01001reg |

^ Регистър или памет: | 1111111w | mod001r / m |

DIV
(DIVide неподписан)

Неподписано разделение

Схема на командата:

div разделител

Цел: да се извърши операция на разделяне на две неподписани двоични стойности.

^ Алгоритъм на работа:
За командата трябва да посочите два операнда - дивидента и делителя. Дивидентът се задава неявно и неговият размер зависи от размера на делителя, който е посочен в командата:

ако делителят е с размер на байта, тогава дивидентът трябва да се намира в регистъра на оси. След операцията коефициентът се поставя в ал, а остатъкът в ах;

ако делителят е дума, тогава дивидентът трябва да бъде разположен в двойка регистри dx: ax, с най-малко значимата част от дивидента в ax. След операцията коефициентът се поставя в ax, а остатъкът е в dx;

ако делителят е двойна дума, тогава дивидентът трябва да се намира в двойката регистър edx: eax, като най-малко значимата част от дивидента е в eax. След операцията коефициентът се поставя в eax, а остатъкът се поставя в edx.

^ Състояние на флаговете след изпълнение на команда:

Приложение:
Командата извършва целочислено деление на операндите с изхода на резултата от делението под формата на коефициент и остатък. При извършване на операция на разделяне може да възникне изключение: 0 - грешка при разделяне. Тази ситуация възниква в един от двата случая: делителят е 0 или коефициентът е твърде голям, за да се побере в регистъра eax / ax / al.

Относно кода на обекта:

| 1111011w | mod110r / m |

INT
(INTerrupt)

Прекъсване на сервизно обаждане

^ Командна схема:

int interrupt_number

Цел: извикване на рутинната услуга за прекъсване с номера на прекъсването, посочен от операнда на инструкцията.

^ Алгоритъм на работа:

натиснете регистъра eflags / flags и върнете адреса в стека. Когато пишете адреса за връщане, първо се записва съдържанието на регистъра на сегмента cs, след това съдържанието на командния указател eip / ip;

нулирайте флаговете if и tf на нула;

прехвърлете управлението на прекъсвача с посочения номер. Механизмът за прехвърляне на управление зависи от режима на работа на микропроцесора.

^ Състояние на флаговете след изпълнение на команда:

Приложение:
Както можете да видите от синтаксиса, има две форми на тази команда:

int 3 - има собствен индивидуален opcode 0cch и заема един байт. Този факт го прави много удобен за използване в различни софтуерни дебъгъри за задаване на точки на прекъсване чрез заместване на първия байт на която и да е команда. Микропроцесорът, срещащ в последователност от команди команда с код на операция 0cch, извиква програмата за обработка на прекъсвания с вектор номер 3, който се използва за комуникация със софтуерния дебъгер.

Втората форма на командата отнема два байта, има код на операция 0cdh и ви позволява да инициирате повикване към рутинна услуга за прекъсване с векторно число в диапазона 0–255. Характеристиките на трансфера на управление, както беше отбелязано, зависят от режима на работа на микропроцесора.

Относно обектния код (два формата):

Регистър: | 01000reg |

^ Регистър или памет: | 1111111w | mod000r / m |

JCC
JCXZ / JECXZ
(Направо, ако условие)

(Скок, ако CX \u003d нула / скок, ако ECX \u003d нула)

Направо, ако условието е изпълнено

Направо, ако CX / ECX е нула

^ Командна схема:

jcc етикет
етикет jcxz
етикет на jecxz

Предназначение: преход в рамките на текущия сегмент от команди, в зависимост от определено условие.

^ Алгоритъм на командите (с изключение на jcxz / jecxz):
Проверка на състоянието на флаговете в зависимост от операционния код (отразява провереното състояние):

ако провереното условие е вярно, отидете на клетката, посочена от операнда;

ако провереното условие е невярно, прехвърлете контрола към следващата команда.

Алгоритъм на командата jcxz / jecxz:
Проверка на условието за равенство на нула от съдържанието на регистъра ecx / cx:

ако провереното състояние

Обща информация за асемблерния език

Символичният асемблерен език ви позволява до голяма степен да премахнете недостатъците на програмирането на машинен език.

Основното му предимство е, че в асемблерния език всички програмни елементи са представени в символна форма. Преобразуването на символните имена на команди в техните двоични кодове се възлага на специална програма - асемблер, която освобождава програмиста от трудоемка работа и премахва неизбежните грешки.

Символните имена, въведени в програмирането на асемблерен език, обикновено отразяват семантиката на програмата, а съкращението на командите - тяхната основна функция. Например: PARAM - параметър, TABLE - таблица, MASK - маска, ADD - добавяне, SUB - изваждане и др. н. Такива имена са лесни за запомняне от програмиста.

За програмиране на асемблерен език трябва да имате сложни инструменти, отколкото при програмиране на машинен език: необходими са компютърни системи, базирани на микрокомпютър или компютър с набор от периферни устройства (буквено-цифрова клавиатура, дисплей на символи, флопидисково устройство и печатащо устройство), както и резидент или междусистемно програмиране за необходимите видове микропроцесори. Асемблерният език ви позволява ефективно да пишете и отстранявате грешки в много по-сложни програми от машинния език (до 1 - 4 KB).

Езиците за сглобяване са машинно ориентирани, т.е.зависими са от машинния език и структурата на съответния микропроцесор, тъй като в тях на всяка микропроцесорна инструкция е присвоено определено символично име.

Асемблерните езици осигуряват значително увеличение на производителността на програмистите в сравнение с машинните езици и в същото време запазват способността да използват всички налични софтуерни хардуерни ресурси на микропроцесора. Това позволява на опитни програмисти да пишат програми, които се изпълняват за по-кратко време и заемат по-малко памет от програмите, написани на език на високо ниво.

В тази връзка почти всички програми за управление на входно / изходни устройства (драйвери) са написани на асемблерен език, въпреки наличието на доста голяма номенклатура от езици на високо ниво.

Използвайки асемблерен език, програмистът може да зададе следните параметри:

мнемоника (символично име) на всяка инструкция на машинния език на микропроцесора;

стандартен формат за редове на асемблерна програма;

формат за определяне на различни методи за адресиране и командни опции;

формат за определяне на символни константи и константи от цяло число в различни бройни системи;

псевдокоманди, които контролират процеса на сглобяване (превод) на програмата.

На асемблерен език програмата се пише ред по ред, тоест за всяка инструкция се отделя по един ред.

За микрокомпютрите, изградени на базата на най-често срещаните видове микропроцесори, може да има няколко варианта на асемблерния език, но обикновено има само едно практическо разпределение - това е така нареченият стандартен асемблерен език

Програмирането на ниво машинна инструкция е минималното ниво, на което е възможно програмирането. Системата от машинни инструкции трябва да е достатъчна за извършване на необходимите действия, като издава инструкции към хардуера на компютъра.

Всяка машинна инструкция се състои от две части:

· Операционна зала - определяне „какво да се прави“;

· Операнд - дефиниране на обекти за обработка, „какво да правя“.

Микропроцесорна машинна инструкция, написана на асемблерен език, е един ред със следната синтактична форма:

етикет команда / директива операнд (и); коментари

В този случай задължителното поле в реда е команда или директива.

Етикетът, командата / директивата и операндите (ако има такива) са разделени с поне един интервал или знак за табулация.

Ако трябва да бъде продължена команда или директива на следващия ред, тогава се използва обратната наклонена черта: \\.

По подразбиране асемблерният език не прави разлика между главни и малки букви, когато пише команди или директиви.

Директно адресиране: Ефективният адрес се определя директно от полето за компенсиране на машинните инструкции, което може да бъде 8, 16 или 32 бита.

mov eax, сума; eax \u003d сума

Асемблерът замества sum със съответния адрес, съхраняван в сегмента с данни (по подразбиране той се адресира от ds регистъра) и стойността, съхранена на адреса на сумата, се поставя в eax регистъра.

Непряко адресиранеот своя страна има следните видове:

· Косвено адресиране на база (регистър);

· Косвено адресиране на база (регистър) с отместване;

· Непряко индексирано адресиране;

· Непряко адресиране на основен индекс.

Косвено адресиране на база (регистър).При такова адресиране ефективният адрес на операнда може да бъде във всеки от регистрите с общо предназначение, с изключение на sp / esp и bp / ebp (това са специфични регистри за работа със сегмент на стека). Синтактично в команда този режим на адресиране се изразява чрез заграждане на името на регистъра в квадратни скоби.

mov eax ,; eax \u003d * esi; * esi стойност при esi

Тема 1.4 Асемблер Мнемоника. Структура и формати на команди. Видове адресиране. Микропроцесорен набор от команди

План:

1 Асемблерен език. Основни понятия

2 Символи на асемблерния език

3 Видове асемблерни изрази

4 Директиви за монтаж

5 Комплект инструкции на процесора

1 iасемблерен език. Основни понятия

Асемблерен език е символно представяне на машинен език. Всички процеси в машината, на най-ниското, хардуерно ниво, се управляват само от команди на езика на машината (инструкции). Следователно е ясно, че въпреки общото име, асемблерният език за всеки тип компютър е различен.

Програмата за асемблер е колекция от блокове памет, наречена сегменти на паметта.Програмата може да се състои от един или няколко такива блокови сегмента. Всеки сегмент съдържа набор от езикови изречения, всеки от които заема отделен ред от програмен код.

Изреченията за събрание са от четири вида:

1) команди или инструкции, които са символни аналози на машинните инструкции. В процеса на превод инструкциите на асемблера се преобразуват в съответните команди от набора инструкции на микропроцесора;

2) макроси -изречения от програмния текст, които са оформени по определен начин, които се заменят по време на излъчването с други изречения;

3) директиви,които са инструкции към асемблерния преводач да извърши някои действия. Директивите нямат аналог в машинното представяне;

4) редове за коментари съдържащи всякакви символи, включително буквите на руската азбука. Коментарите се пренебрегват от преводача.

­ Структурата на сборна програма. Синтаксис на събранието.

Изреченията, които съставляват програма, могат да бъдат синтактична конструкция, съответстваща на команда, макрос, директива или коментар. За да може асемблерният преводач да ги разпознае, те трябва да се формират според определени синтактични правила. Най-добрият начин да направите това е да използвате официално описание на синтаксиса на езика, като граматичните правила. Най-често срещаните начини за описване на език за програмиране като този - синтаксични диаграми - и разширени форми на Бакус-Наур. По-удобно за практическа употреба синтаксисни диаграми.Например синтаксисът на асемблерните изречения може да бъде описан, като се използват синтаксисните диаграми, показани на следващите фигури 10, 11, 12.

Фигура 10 - Формат на изречение на асемблер


­ Фигура 11 - Формат на директивите

­ Фигура 12 - Формат на команди и макроси

На тези фигури:

­ име на етикета - идентификатор, чиято стойност е адресът на първия байт от изречението на изходния текст на програмата, който той обозначава;

­ име - идентификатор, който отличава тази директива от други директиви със същото име. В резултат на обработката на асемблерен език на конкретна директива на това име могат да бъдат присвоени определени характеристики;

­ opcode (COP) и директива - те са мнемонични обозначения на съответната машинна инструкция, макрос или директива на преводача;

­ операнди - части от команда, макрос или асемблер директива, които обозначават обекти за манипулиране. Операндите на асемблера се описват чрез изрази с числови и текстови константи, етикети и идентификатори на променливи, като се използват операционни знаци и някои запазени думи.

Синтаксисните диаграми помагат намерете и след това преминете от входа на диаграмата (вляво) към нейния изход (вдясно). Ако такъв път съществува, тогава изречението или конструкцията са синтактично правилни. Ако няма такъв път, тогава компилаторът няма да приеме тази конструкция.

­ 2 Символи на асемблерния език

Разрешените знаци при писане на програмен текст са:

1) всички латински букви: A-Z, a-z... В този случай главни и малки букви се считат за еквивалентни;

2) номера от 0 преди 9 ;

3) знаци ? , @ , $ , _ , & ;

4) сепаратори , . () < > { } + / * % ! " " ? = # ^ .

Изреченията на асемблера се образуват от жетони, които са синтактично неразделни последователности от валидни езикови символи, които имат смисъл за преводач.

Лексеми са:

1) идентификатори - поредици от валидни символи, използвани за обозначаване на програмни обекти като кодове за опции, имена на променливи и имена на етикети. Правилото за писане на идентификатори е следното: идентификаторът може да се състои от един или повече знака;

2) символни низове - последователности от символи, затворени в единични или двойни кавички;

3) цели числа на една от следните бройни системи : двоичен, десетичен, шестнадесетичен. Идентифицирането на числата при тяхното записване в асемблерни програми се извършва съгласно определени правила:

4) десетичните числа не изискват никакви допълнителни символи за тяхната идентификация, например 25 или 139. За идентификация в изходния код на програмата двоични числа след написването на нулите и онези, включени в състава им, е необходимо да поставите латиница „ б”, Например 10010101 б.

5) шестнадесетичните числа имат повече конвенции, когато са написани:

Първо, те се състоят от числа 0...9 , малки и главни букви на латинската азбука а, б, ° С, д, д, е или A, Б., ° С, д, Е., F.

На второ място, преводачът може да има затруднения при разпознаването на шестнадесетични числа поради факта, че те могат да се състоят или само от цифри 0 ... 9 (например 190845), или да започват с буква от латинската азбука (например, ef15). За да „обясни“ на преводача, че даден маркер не е десетично число или идентификатор, програмистът трябва да избере шестнадесетично число по специален начин. За да направите това, в края на последователността от шестнадесетични цифри, съставляващи шестнадесетично число, напишете латинската буква „ з”. Това е предпоставка. Ако шестнадесетично число започва с буква, пред него се изписва водеща нула: 0 ef15 з.

Почти всяко изречение съдържа описание на обекта, върху който или с помощта на който се извършва някакво действие. Тези обекти се извикват операнди... Те могат да бъдат определени по този начин: операнди - това са обекти (някои стойности, регистри или клетки от паметта), върху които се действа чрез инструкции или директиви, или те са обекти, които дефинират или изясняват действието на инструкциите или директивите.

Възможно е да се извърши следната класификация на операндите:

­ постоянни или непосредствени операнди;

­ адресни операнди;

­ подвижни операнди;

брояч на адреси;

­ регистър операнд;

­ базови и индексни операнди;

­ структурни операнди;

записи.

Операндите са елементарни компоненти, които формират част от машинна инструкция, която обозначава обектите, върху които се извършва операция. В по-общ случай операндите могат да бъдат включени като съставни части в по-сложни формации, наречени изрази.

Изрази са комбинации от операнди и оператори, разглеждани като цяло. Резултатът от оценката на даден израз може да бъде адрес на някаква клетка памет или някаква постоянна (абсолютна) стойност.

­ 3 Видове асемблерни изрази

Нека изброим възможните типове асемблерни оператори и синтактични правила за образуване на асемблерни изрази:

­ аритметични оператори;

­ оператори на смяна;

­ оператори за сравнение;

­ логически оператори;

­ индекс оператор;

­ оператор за заместване на типа;

­ оператор за заместване на сегмент;

­ оператор за именуване на тип структура;

­ оператор за получаване на сегментния компонент на адреса на израза;

­ оператор, за да получи отместването на израз.

1 Директиви на асемблера

­ Директивите на асемблера са:

1) Директиви за сегментиране. В хода на предишната дискусия открихме всички основни правила за писане на команди и операнди в асемблерна програма. Въпросът за това как правилно да се формулира последователността от команди, така че преводачът да може да ги обработи и микропроцесорът да ги изпълни, остава отворен.

Когато разглеждахме архитектурата на микропроцесора, научихме, че той има шест сегментни регистри, чрез които може да работи едновременно:

­ с един кодов сегмент;

­ с един сегмент на стека;

­ с един сегмент от данни;

­ с три допълнителни сегмента от данни.

Физически сегментът е област на паметта, заета от инструкции и (или) данни, чиито адреси се изчисляват спрямо стойността в съответния регистър на сегмента. Синтаксичното описание на сегмент в асемблера е конструкцията, показана на Фигура 13:


­ Фигура 13 - Синтактично описание на сегмента в асемблера

Важно е да се отбележи, че функционалността на даден сегмент е малко по-широка от простото разделяне на програма на блокове с код, данни и стек. Сегментирането е част от по-общ механизъм, свързан с концепцията за модулно програмиране. Той включва унифициране на дизайна на обектни модули, създадени от компилатора, включително тези от различни програмни езици. Това ви позволява да комбинирате програми, написани на различни езици. Операндите в директивата SEGMENT са предназначени да реализират различни варианти на такъв съюз.

2) Директиви за управление на списъка. Директивите за контрол на списъка са разделени на следните групи:

­ общи директиви за контрол на списъка;

­ извежда директиви към списъка на включените файлове;

­ директиви за извеждане на блокове за условно сглобяване;

­ директиви за изброяване на макроси;

­ директиви за извеждане на информация за препратки към списъка;

­ директиви за промяна на формата на списъка.

2 Комплект инструкции на процесора

Наборът от инструкции на процесора е показан на Фигура 14.

Нека разгледаме основните групи команди.

­ Фигура 14 - Класификация на инструкциите за асемблер

Екипите са:

1 Команди за пренос на данни. Тези команди са много важни в набора от инструкции на всеки процесор. Те изпълняват следните основни функции:

­ съхраняване на съдържанието на вътрешните регистри на процесора в паметта;

­ копиране на съдържание от една област на паметта в друга;

­ запис на I / O устройства и четене от I / O устройства.

На някои процесори всички тези функции се изпълняват от една единствена командаMOV (за прехвърляне на байтове -MOVB ) но с различни методи за адресиране на операндите.

На други процесори освен командатаMOV има още няколко команди за изпълнение на изброените функции. Също така командите за пренос на данни включват команди за обмен на информация (обозначението им се основава на думатаОбмен ). Обменът на информация между вътрешните регистри, между две половини на един регистър (РАЗМЯНА ) или между регистър и място в паметта.

2 Аритметични команди. Аритметичните инструкции третират кодовете на операндите като цифрови двоични или BCD кодове. Тези команди могат да бъдат разделени на пет основни групи:

­ команди за операции с фиксирана точка (събиране, изваждане, умножение, деление);

­ команди с плаваща запетая (събиране, изваждане, умножение, деление);

­ команди за почистване;

­ команди за увеличаване и намаляване;

­ команда за сравнение.

3 Командите за операции с фиксирана точка действат върху кодове в регистрите на процесора или в паметта, както при обичайните двоични кодове. Инструкциите с плаваща запетая (точка) използват формата на представяне на числата с ред и мантиса (обикновено тези числа заемат две последователни места в паметта). В съвременните мощни процесори наборът от инструкции с плаваща запетая не се ограничава само до четири аритметични операции, но съдържа и много други по-сложни инструкции, например изчисляването на тригонометрични функции, логаритмични функции, както и сложни функции, необходими за обработка на звук и изображения.

4 Инструкциите за изчистване са предназначени за записване на нулев код в регистър или клетка памет. Тези команди могат да бъдат заменени с нулеви команди за прехвърляне, но специалните ясни команди обикновено са по-бързи от командите за прехвърляне.

5 Команди за увеличаване (увеличаване с едно) и намаляване

(намаления от един) също са много удобни. Те по принцип могат да бъдат заменени с добавяне с една или изваждане на една команда, но нарастването и намаляването са по-бързи от събирането и изваждането. Тези инструкции изискват един входен операнд, който също е изходен операнд.

6 Инструкцията за сравнение сравнява два входни операнда. Всъщност той изчислява разликата между тези два операнда, но не формира изходен операнд, а само променя битовете в регистъра на състоянието на процесора от резултата от това изваждане. Следващата инструкция след инструкцията за сравнение (обикновено инструкция за разклонение) ще анализира битовете в регистъра на състоянието на процесора и ще извърши действия в зависимост от техните стойности. Някои процесори предоставят инструкции за маргаритка, свързваща две последователности от операнди в паметта.

7 Логически команди. Логическите инструкции изпълняват логически (побитови) операции върху операндите, т.е. те разглеждат кодовете на операндите не като единично число, а като набор от отделни битове. По този начин те се различават от аритметичните команди. Логическите команди изпълняват следните основни операции:

­ логическо И, логично ИЛИ, добавяне по модул 2 (Изключително ИЛИ);

­ логически, аритметични и циклични отмествания;

­ проверка на битове и операнди;

­ настройка и изчистване на битове (флагове) на регистъра на състоянието на процесора (PSW).

Логическите инструкции ви позволяват да изчислявате основни логически функции от два входни операнда бит по бит. В допълнение, операцията AND се използва за принудително изчистване на посочените битове (като един от операндите се използва код на маска, в който битовете, които трябва да бъдат изчистени, са зададени на нула). Операцията ИЛИ се използва за принудително задаване на посочените битове (като един от операндите се използва код на маска, при който цифрите, изискващи настройка на едно, са равни на едно). Операцията "XOR" се използва за инвертиране на посочените битове (като един от операндите се използва код на маска, в който битовете, които трябва да се обърнат, са зададени на един). Инструкциите изискват два входни операнда и образуват един изходен операнд.

8 Командите Shift ви позволяват да преместите битовия код на операнда надясно (към долните битове) или наляво (към по-високите битове). Типът смяна (логическа, аритметична или циклична) определя каква ще бъде новата стойност на най-значимия бит (при преместване надясно) или най-малко значимия бит (при преместване наляво), а също така определя дали предишната стойност на най-значимия бит (при преместване наляво) ще бъде запазена някъде или най-малко значимият бит (когато е изместен надясно). Цикличните отмествания позволяват битовете на операнда да се изместват кръгово (по посока на часовниковата стрелка, когато се измести надясно, или обратно на часовниковата стрелка, когато се измести наляво). В този случай флагът за носене може или не може да бъде включен в пръстена за смяна. Битът за флаг за пренасяне (ако се използва) съхранява стойността на най-значимия бит, когато се циклира вляво и най-малко значимия бит, когато се циклира вдясно. Съответно, стойността на бита за флаг за пренасяне ще бъде презаписана в най-малко значимия бит при колоездене вляво и в най-значимия бит при колоездене вдясно.

9 Команди за преходи. Инструкциите за прескачане са предназначени да организират всякакви цикли, клонове, извиквания на подпрограми и т.н., тоест нарушават последователния поток на програмата. Тези команди записват нова стойност в регистъра на броячите на команди и по този начин карат процесора да премине не към следващата команда по ред, а към всяка друга команда в паметта на програмата. Някои команди за преход осигуряват по-нататъшно връщане обратно към точката, от която е извършен преходът, други не предвиждат това. Ако е осигурено връщане, текущите параметри на процесора се съхраняват в стека. Ако не се предостави връщане, текущите параметри на процесора не се запазват.

Командите за преход без проследяване са разделени на две групи:

­ команди за безусловен скок;

­ команди за условен скок.

Тези команди използват думитеКлон (клон) и скок (скок).

Инструкциите за безусловно прескачане причиняват преход към нов адрес, независимо от всичко. Те могат да причинят скок с определено количество отместване (напред или назад) или до определен адрес в паметта. Стойността на отместването или новата стойност на адреса е посочена като входен операнд.

Командите за условен скок не винаги причиняват скок, а само когато са изпълнени посочените условия. Тези условия обикновено са стойностите на флаговете в регистъра на състоянието на процесора (PSW ). Тоест условието за преход е резултат от предишната операция, която променя стойностите на флага. Такива условия за скок могат да бъдат общо от 4 до 16. Няколко примера за условни команди за скок:

­ преход, ако е равен на нула;

­ преход, ако не е равен на нула;

­ скок, ако има преливане;

­ скок, ако няма преливане;

­ преход, ако е по-голям от нула;

­ скочи, ако е по-малко или равно на нула.

Ако условието за преход е изпълнено, новата стойност се зарежда в командния регистър. Ако условието за скок не е изпълнено, броячът на инструкциите просто се увеличава и процесорът избира и изпълнява следващата инструкция по ред.

Командата за сравнение (CMP), която предшества командата за условен скок (или дори няколко команди за условен скок), се използва специално за проверка на условията за скок. Но флаговете могат да бъдат зададени от всяка друга команда, например команда за прехвърляне на данни, всяка аритметична или логическа команда. Обърнете внимание, че самите команди за прескачане не променят флаговете, което просто ви позволява да поставите няколко команди за прескачане една след друга.

Командите за прекъсване заемат специално място сред командите за връщане назад. Тези инструкции изискват номер на прекъсване (векторен адрес) като входен операнд.

Заключение:

Асемблерният език е символично представяне на машинен език. Езикът за сглобяване за всеки тип компютър е различен. Програмата за асемблерен език е колекция от блокове памет, наречени сегменти на паметта. Всеки сегмент съдържа набор от езикови изречения, всеки от които заема отделен ред от програмен код. Изреченията за сглобяване са от четири типа: команди или инструкции, макроси, директиви, редове за коментари.

Всички латински букви са валидни символи при писане на текст на програмата: A-Z, a-z... В този случай главни и малки букви се считат за еквивалентни; фигури от 0 преди 9 ; знаци ? , @ , $ , _ , & ; сепаратори , . () < > { } + / * % ! " " ? = # ^ .

Прилагат се следните типове асемблерни изрази и синтактични правила за генериране на асемблерни изрази. аритметични оператори, оператори за смяна, оператори за сравнение, логически оператори, оператор на индекс, оператор за заместване на тип, оператор за заместване на сегмент, оператор за именуване на тип структура, оператор за получаване на сегментния компонент на адрес на израз, оператор за получаване на отместване на израз.

Командната система е разделена на 8 основни групи.

­ Тестови въпроси:

1 Какво е асемблерен език?

2 Какви символи могат да се използват за писане на команди на асемблерен език?

3 Какво представляват етикетите и тяхното предназначение?

4 Обяснете структурата на командите на асемблера.

5 Избройте 4 вида асемблерни изречения.

Програмирането на ниво машинна инструкция е минималното ниво, на което е възможно програмирането. Системата от машинни инструкции трябва да е достатъчна за извършване на необходимите действия, като издава инструкции към хардуера на компютъра.

Всяка машинна инструкция се състои от две части:

  • операционна зала - определяне „какво да се прави“;
  • операнд - дефиниране на обекти за обработка, "какво да правя".

Микропроцесорна машинна инструкция, написана на асемблерен език, е един ред със следната синтактична форма:

етикет на команда / директива операнд (и); коментари

В този случай задължителното поле в реда е команда или директива.

Етикетът, командата / директивата и операндите (ако има такива) са разделени с поне един интервал или знак за табулация.

Ако трябва да бъде продължена команда или директива на следващия ред, тогава се използва обратната наклонена черта: \\.

По подразбиране асемблерният език не прави разлика между главни и малки букви, когато пише команди или директиви.

Примери за редове на код:

Брой db 1 ; Име, директива, един операнд
mov eax, 0 ; Команда, два операнда
cbw; Команда

Етикети

Етикет на асемблерен език може да съдържа следните знаци:

  • всички букви от латинската азбука;
  • числа от 0 до 9;
  • специални знаци: _, @, $,?.

Точка може да се използва като първи символ на етикет, но някои компилатори не препоръчват използването на този знак. Запазените имена на асемблери (директиви, оператори, имена на команди) не могат да се използват като етикети.

Първият знак в етикета трябва да бъде буква или специален знак (но не и цифра). Максималната дължина на етикета е 31 знака. Всички етикети, които са написани на ред, който не съдържа асемблерна директива, трябва да завършват с двоеточие :.

Команди

Команда казва на преводача какво действие трябва да предприеме микропроцесорът. В сегмент от данни команда (или директива) дефинира поле, работна област или константа. В сегмента на кода командата дефинира действието, като например прехвърляне (mov) или добавяне (добавяне).

Директиви

Асемблерът има редица оператори, които ви позволяват да контролирате процеса на сглобяване и генериране на списък. Тези оператори се извикват директиви ... Те действат само в процеса на сглобяване на програмата и за разлика от инструкциите не генерират машинни кодове.

Операнди

Операнд - обект, върху който се изпълнява машинна инструкция или оператор на език за програмиране.
Инструкцията може да има един или два операнда или изобщо да няма операнди. Броят на операндите е имплицитно определен от командния код.
Примери:

  • Няма ret операнди; Връщане
  • Един операнд inc ecx; Увеличете ecx
  • Два операнда добавят eax, 12; Добавете 12 към eax

Етикетът, командата (директивата) и операндът не трябва да започват на определена позиция в низа. Препоръчително е обаче да ги запишете в колона за по-добра четливост на програмата.

Операндите могат да бъдат

  • идентификатори;
  • низове от символи, затворени в единични или двойни кавички;
  • цели числа в двоична, осмична, десетична или шестнадесетична нотация.
Идентификатори

Идентификатори - поредици от валидни символи, използвани за обозначаване на програмни обекти като кодове за опции, имена на променливи и имена на етикети

Правила за писане на идентификатори.

  • Идентификаторът може да бъде един или повече знака.
  • Като символи могат да се използват букви от латинската азбука, цифри и някои специални знаци: _,?, $, @.
  • Идентификаторът не може да започва с цифров знак.
  • Идентификаторът може да бъде с дължина до 255 знака.
  • Преводачът приема първите 32 знака от идентификатора и игнорира останалите.
Коментари

Коментарите са отделени от изпълнимия ред с a; ... В този случай всичко, което е написано след символа с точка и запетая и до края на реда, е коментар. Използването на коментари в програмата подобрява нейната яснота, особено когато целта на набора от инструкции не е ясна. Коментарът може да съдържа всякакви знаци за печат, включително интервал. Коментарът може да обхваща целия ред или да следва команда на същия ред.

Структурата на сборна програма

Програма, написана на асемблерен език, може да бъде съставена от няколко части, наречена модули ... Всеки модул може да има дефинирани един или повече данни, стек и кодови сегменти. Всяка пълна програма за сглобяване трябва да включва един основен или основен модул, от който да започне нейното изпълнение. Модулът може да съдържа кодови сегменти, сегменти от данни и сегменти на стека, декларирани с помощта на съответните директиви. Преди да декларирате сегменти, трябва да посочите модела на паметта, използвайки директивата .MODEL.

Пример за програма за асемблерен език „нищо не прави“:

686P
.MODEL FLAT, STDCALL
.ДАННИ
.КОД
СТАРТ:

RET
КРАЙ СТАРТ

Тази програма съдържа само една инструкция за микропроцесор. Тази команда е RET. Той осигурява правилното прекратяване на програмата. По принцип тази команда се използва за излизане от процедура.
Останалата част от програмата е свързана с работата на преводача.
.686P - Разрешени са команди за защитен режим на Pentium 6 (Pentium II). Тази директива избира поддържания набор от инструкции за асемблер, като посочва модела на процесора. Буквата P в края на директивата информира преводача, че процесорът работи в защитен режим.
.MODEL FLAT, stdcall е плосък модел памет. Този модел памет се използва в операционната система Windows. stdcall
.DATA - програмен сегмент, съдържащ данни.
.CODE - блок на програмата, съдържащ кода.
START е етикет. В асемблерния език етикетите играят голяма роля, което не е така в съвременните езици на високо ниво.
END START - краят на програмата и съобщение до преводача, че програмата трябва да бъде стартирана от етикета START.
Всеки модул трябва да съдържа директива END, за да маркира края на изходния код на програмата. Всички редове, които следват директивата END, се игнорират. Ако пропуснете директивата END, се генерира грешка.
Етикетът, посочен след директивата END, казва на преводача името на основния модул, от който стартира програмата. Ако програмата съдържа един модул, етикетът след директивата END може да бъде пропуснат.

Споделя това