Основи на сглобяването
-
Алена Раевская преди 2 години Прегледи:
4 стойности като такива могат да бъдат само математически копроцесор. Работата с реални числа изисква отделно разглеждане. Числата без знак се представят чрез обичайното преобразуване на числа в двоични; следователно обхватът на числата без знак е: 0. 2n - 1, където n е капацитетът на числото. Най-значимият бит на числата със знак показва знака на числото: ако най-значимият бит е единица, тогава числото е отрицателно. Всички останали битове са абсолютната стойност на числото. Диапазон от числа със знак: - 2 n n-1-1. Принципите на събиране и изваждане на цели числа, числа със знак и без знак са еднакви; разликите възникват при умножение и деление на числа. Инструкции SUB и ADD Инструкцията ADD, както подсказва името, добавя и двата операнда и съхранява резултата в дестинационния операнд. Синтаксисът на командата ADD е: add , . Форматът на операндите е идентичен с формата на операндите на инструкцията MOV. Двата операнда се добавят и резултатът се съхранява в дестинацията. След операцията по добавяне в зависимост от резултата се сменят съответните битове във флаговия регистър. Може да се предположи, че инструкцията SUB извършва изваждане - или, за да бъдем по-точни, тя изважда операнда източник от операнда местоназначение и го съхранява в операнда местоназначение. Синтаксисът на командата SUB е идентичен с командата ADD. Ако след добавяне (изваждане) на два операнда, резултатът не се побира в операнда местоназначение (числото е твърде голямо и отрицателно), възниква препълване и флагът OF е зададен на 1. Ако се появи пренасяне или заемане от най-значимия бит (например от бит 17 или 33), тогава се задава флагът за пренасяне. Обикновено тези два флага винаги се придружават един друг, т.е. ако единият е зададен, тогава е зададен и вторият. В случай на изваждане,и флагът за препълване не е зададен. Има и още две инструкции за увеличаване и намаляване на операнда - това са INC и DEC. Тези инструкции увеличават и намаляват операнда съответно с единица. Те приемат само един операнд, който може да бъде регистър или стойност от паметта. Размерът на операнда може да бъде произволен (1, 2, 4, 8 байта). Както числата със знак, така и числата без знак могат да се използват като параметри за всички горни команди. Умножение и деление Инструкцията MUL е умножение без знак. Синтаксис на командата: mul. Инструкцията MUL умножава операнда с регистъра EAX(AL, AX, RAX) и го съхранява в регистрите EDX:EAX (AX, DX:AX, RDX:RAX). Операндът може да бъде регистър или стойност в паметта. В табл. 1.7 показва възможните резултати от тази команда. Таблица 1.7. Зависимост на резултата от командата MUL от размера на операнда Размер на операнда Резултат 1 байт AX = AL * 2 байта DX:AX = AX * 4 байта EDX:EAX = EAX * 8 байта RDX: RAX = RAX * DIV команда - деление без знак. Синтаксис на командата: div. Инструкцията DIV разделя регистрите EDX:EAX (AX, DX:AX, RDX:RAX) на операнд и съхранява резултата от разделянето в EAX (AL, AX, RAX) и остатъка от деленето в EDX (AH, DX, RDX). В табл. 1.8 показва възможните резултати от тази команда.
5 Таблица 1.8. Зависимост на резултата от командата DIV от размера на операнда Размер на операнда Източник Резултат от деленето Остатък от делението 1 байт AX AL AN 2 байта DX:AX AX DX 4 байта EDX: EAX EAX EDX 8 байта RDX: RAX RAX RDX Команда IMUL - умножение със знак. Инструкцията може да отнеме до три операнда. Тази инструкция има три нотационни форми, в зависимост от това колко операнда са посочени. 1. Първата форма е само един операнд. Командата работи точно както MUL, само умножението е със знак. 2. Втората форма е два операнда. Синтаксис: imul, . Първият операнд може да бъде само общ регистър, докато вторият операнд може да бъде регистър, стойност от паметта или самата стойност. Операндите могат да бъдат с произволен размер, но ако вторият операнд сам по себе си е стойност, тогава той не може да бъде с размер 8 байта. Първият операнд се умножава знаково по втория и резултатът се съхранява в първия операнд. 3. Третата форма е три операнда. Формат: imul , , . Като първи операнд може да се използва само общ регистър. Вторият операнд може да бъде регистър или стойност от паметта. Първият и вторият операнд трябва да са с еднакъв размер. Третият операнд може да бъде само непосредствена стойност и не може да бъде 8 байта. С тази форма инструкцията умножава втория операнд по третия операнд и съхранява резултата в първия операнд. Командата IDIV е разделяне със знак. Командата IDIV е напълно идентична с командата DIV по отношение на резултата от нейната работа. Разликата между инструкцията IDIV и DIV е, че ако операндите имат различни знакови битове, тогава резултатът (коефициент и остатък) ще бъде отрицателен; ако знаковите битове на операндите са равни, тогава резултатът (коефициент и остатък) ще бъде положителен. Командите DIV и IDIV не влияят на регистъра на флаговете. Инструкцията MUL задава флаговете OF и CF на нула, ако високата част от резултата (AH, DX, EDX, RDX) е нула; във всеки друг случай тези битове са зададени на единица. Когато използвате инструкцията IMUL в първата форма, флаговете OF и CF се настройват на единица, ако някакви значими битове са пренесени във високата част на резултата (AH, DX, EDX, RDX), и на нула, ако не е имало пренасяне във високата част на резултата. По този начин, ако флаговете OF и CF са изчистени, тогава резултатът може да бъде прочетен само от долната част и той ще бъде правилен. ИзползвайкиIMUL инструкции във втората и третата форма, флаговете OF и CF се задават на единица, ако размерът на резултата е по-голям от размера на операнда, указан като резултат. По този начин, ако флаговете OF и CF са зададени след операцията за умножение, тогава продуктът в получения операнд е неправилен (скъсен). Логически операции Има няколко основни логически операции: операцията "или" (команда OR), логическо "и" (команда AND), логическо отрицание (команда NOT), "изключително или" (команда XOR).
6 Командата ИЛИ е битова логическа операция ИЛИ. Синтаксис на командата: или , . Тази инструкция извършва побитово логическо събиране между дадените операнди и съхранява резултата в дестинацията. Операндите могат да бъдат с размер 1, 2, 4, 8 байта. При логическо събиране резултатът е единица (вярно), ако някой от операндите е верен. Командата И е малко логична операция И Синтаксис на командата: и , . Тази инструкция извършва побитово логическо умножение на предадените операнди и съхранява резултата в дестинацията. Операндите могат да бъдат с размер 1, 2, 4, 8 байта. При логическото умножение резултатът е единица (вярно), ако и двата операнда са верни. Инструкцията NOT е операция за побитово логическо отрицание. Синтаксис на командата: не . Тази инструкция изпълнява побитово логическо отрицание на операнда. При логическото отрицание резултатът е отрицанието на операнда, т.е., ако е 1, тогава се получава 0, ако е 0, тогава се получава 1. Операндът може да бъде с размер 1, 2, 4, 8 байта. Командата XOR е побитова операция XOR. Синтаксис на командата: xor , . Инструкцията XOR изпълнява побитова операция XOR върху дадените операнди и съхранява резултата в дестинацията. Операндите могат да бъдат с размер 1, 2, 4, 8 байта. Ако операндите са еднакви, тогава резултатът е 0, ако са различни, тогава 1. ТакаПо този начин, ако посочите един и същ регистър като двата операнда, тогава регистърът ще бъде настроен на нула. Тази техника може да бъде много полезна при оптимизиране на код. И четирите горни логически операции, в зависимост от резултата от операцията, променят съответните битове във флаговия регистър. Shifts Shift е побитово изместване на операнд надясно или наляво. Например преместването на число с 3 ще доведе до това, че всички команди за преместване имат един и същ синтаксис: команда , . Има различни видове смени: циклични, аритметични и логически. Да започнем с логическите. SHL - логично ляво изместване. Инструкцията измества операнда наляво с определения брой битове. Освободените отдясно битове се запълват с нули. Стойността на CF е стойността на бита, който последно е бил избутан от левия край на операнда. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако броят на битовете е 1, тогава OF = 0, докато 2-та най-значещи бита от оригиналната стойност на дестинационния операнд съвпадат; иначе OF = 1. SHR - логическо изместване надясно. Инструкцията измества операнда надясно с определения брой битове. Освободените отдясно битове се запълват с нули. Стойността на CF е стойността на бита, който последно е бил избутан от десния край на операнда. Ако знаковият бит запазва стойността си, тогава знакът за препълване OF = 0, в противен случай OF = 1. Стойността на CF е същата като стойността на бита, който последно е бил избутан отвъд десния край на операнда. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако числото е 1, тогава флагът OF е равен на стойността на най-значимия бит на оригиналния операнд. SAL - аритметично ляво изместване. Командата е напълно идентична с командата SHL. Това е същата команда, само имената са различни. SAR - аритметично изместване надясно. Командата е идентична с командата SHR, с изключение на товаче всеки нововмъкнат бит отляво е равен на най-значимия бит от оригиналния операнд. По този начин, по време на аритметично изместване надясно, операндът няма да промени знака си. Например преместването на число с 3 бита надясно води до
7 ROL - циклично изместване наляво. Инструкцията измества операнда наляво с определения брой битове. Малко, което надхвърля лявата граница, се вмъква отдясно. Стойността на CF е стойността на бита, който последно е бил избутан от левия край на операнда. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако броят на битовете е равен на 1, тогава резултатът от изключителната операция „или“, приложена към 2-та най-значими бита от първоначалната стойност на операнда, се въвежда във флага OF. ROR - циклично изместване надясно. Инструкцията измества операнда надясно с определения брой битове. Малко, което надхвърля лявата граница, се вмъква отляво. Стойността на CF е стойността на бита, който последно е бил избутан от десния край на операнда. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако броят на битовете е равен на 1, тогава резултатът от операцията XOR, приложена към 2-та най-значими бита на резултата, се въвежда в OF. RCL - циклично ляво изместване чрез CF флаг. Инструкцията измества операнда наляво с определения брой битове. Битът, който е извън левия край, се задава на флага CF, а старата стойност на CF се задава на освободения десен бит. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако броят на битовете е 1, тогава резултатът от изключителната операция „или“, приложена към 2-та най-значещи бита на резултата, се въвежда в OF. RCR - циклично изместване надясно през флага CF. Инструкцията измества операнда надясно с определения брой битове. Битът, който излиза от десния ръб, е маркиран.CF и старата стойност на CF се въвежда в освободения ляв бит. Ако броят на битовете не е равен на 1, тогава флагът за препълване на OF не е дефиниран. Ако броят на битовете е 1, тогава резултатът от изключителната операция „или“, приложена към 2-та най-значещи бита на резултата, се въвежда в OF. За всички команди целевият операнд може да бъде с размер 1,2,4,8 байта. Етикети, данни, скокове Условните и безусловните скокове са съществена част от всяка програма; те ви позволяват да пишете програми с разклонени и циклични алгоритми. Данни Данните в програмите на асемблерния език се декларират (или запазват) с помощта на директиви за данни. Директиви за дефиниране на данни и техните размери. Размер (байтове) Дефиниране на данни 1 DB 2 DW, DU 4 DD 6 DF, DP 8 DQ 10 DT Директивата за описание на данни трябва да бъде последвана от една или повече цифрови стойности, разделени със запетая. Тези изрази дефинират стойности за най-простите елементи от данни, чийто размер зависи от това коя директива се използва. Вместо числова стойност може да има знак; по-късно ще се интерпретира като цифровия код на символа(ите). db 67h db 5dh, 0f6h db "z"; същото като db 7ah db "w", "k", "y" dw 8a34h, 0c51h, 8bh
12 JNZ X!= Y ZF = 0 JO OF = 1 JP PF = 1 JPE PF = 1 JPO PF = 0 JS SF = 1 JZ Z = 1 Понякога има смисъл да използвате командата TEST. Форматът на тази инструкция е почти същият като този на CMP инструкцията, с изключение на това, че вторият операнд не може да бъде стойност от паметта. Тази команда изпълнява операция "логическо И" и променя само флаговете SF, ZF, PF. Инструкцията TEST е полезна за проверка дали стойността на операнд съответства на някаква битова маска. Цикли Понякога едно и също действие трябва да се извърши няколко пъти; за това броячът на повторенията може да бъде поставен в определен регистър и с всяко повторение да намалява сединица този регистър. Ако е равно на нула, тогава не е необходимо да повтаряте действието. mov ex, metkal: loop stele> dec ex jnz metkal Последните два реда са кодът, който организира цикъла. Инструкцията DEC намалява стойността на регистъра ECX и ако тя стане нула, тогава единица ще бъде поставена в ZF флага; в резултат на това, ако регистърът не е равен на нула, тогава ще има преход към етикета. Но има по-лесен начин за организиране на цикъла. Инструкцията LOOP приема най-близкия етикет като единствен операнд. Той намалява регистъра ECX (CX, RCX) с единица и ако този регистър не е равен на нула, тогава управлението се прехвърля към етикета. Единственото предимство на тази команда е, че заема по-малко място. Има и две команди за цикъл: LOOPE (LOOPZ) и LOOPNE (LOOPNZ). Командата LOOPE проверява ZF флага преди прехвърляне на управлението и ако не е зададено, тогава прехвърлянето на управлението не се извършва. Обратното действие се извършва от командата LOOPNE: ако флагът ZF е зададен, тогава не се извършва прехвърляне на управление. При съвременните процесори цикълът с инструкции DEC/JNZ/JZ е за предпочитане от гледна точка на производителността; като цяло те ще се изпълняват два пъти по-бързо от една инструкция LOOP. Работа с флагове на процесора Състоянието на някои от по-често използваните битове в регистъра на флаговете може да се промени с помощта на специални команди. Командите, които работят с процесорни флагове, са изброени по-долу: 1. CLC - нулиране на флага за пренасяне (CF=0). 2. CLD - флаг за изчистена посока (DF=0). 3. CLI - нулиране на флага за разрешаване на прекъсване (IF=0). 4. LAHF - запазване на съдържанието на първия байт от флаговия регистър в регистъра AH (флагове SF, ZF, AF, PF, CF)