- •2. Команди додавання і віднімання.
- •3. Команди множення й ділення.
- •Індивідуальні завдання:
- •Контрольний приклад
- •Індивідуальні завдання:
- •Контрольний приклад
- •Індивідуальні завдання:
- •Контрольний приклад
- •Індивідуальні завдання.
- •Команда lea. При використанні регістрів-модифікаторів часто доводиться записувати в них ті чи інші адреси. Нехай, наприклад, нам необхідно занести в регістр вх адресі змінної X:
- •Контрольний приклад
- •1. Сегментування адрес у пк
- •1.1. Загальна схема базування адрес
- •1.2. Особливості сегментування адрес у пк
- •Zzzzz - абсолютна адреса
- •1.3. Сегментні регістри за замовчуванням
- •2. Програмні сегменти
- •2.1. Значення імені сегмента
- •2.2. Адресні змінні
- •Bl dw а2 еквівалентно Bl dw offset а2 в2 dd а2 еквівалентно в2 dd вод а2 : offset a2
- •Індивідуальні завдання:
- •Контрольний приклад
- •1. Схема базування адреси в пк?
- •Invoke виpаз [, аpгументи]
- •Invoke ExitProcess, 0
- •Invoke ExitProcess, 0
- •Invoke MessageBox, null, addr MsgBoxText, addr MsgBoxCaption, mb_ok
- •Invoke ExitProcess, null
- •Invoke MessageBox,null, addr MsgBoxText,addr MsgBoxCaption,mb_ok
- •Хід роботи:
- •Написати програму, що створює полнофункціональну Windows пpогpаму, яка виводить повідомлення "Win32 assembly is great!".
- •Контрольні питання:
- •Лабораторна робота n 2
- •Теоретичні відомості.
- •Invoke LoadIcon,null,idi_application
- •Invoke LoadCursor,null,idc_arrow
- •Invoke RegisterClassEx, addr wc ; Регістpація нашого класу вікна
- •Inst:hinstance,hPrevInst:hinstance,CmdLine:lpstr,CmdShow:dword
- •Invoke LoadIcon,null,idi_application
- •Invoke LoadCursor,null,idc_arrow
- •Invoke RegisterClassEx, addr wc
- •Invoke ShowWindow, hwnd,CmdShow
- •Invoke UpdateWindow, hwnd
- •Invoke GetMessage, addr msg,null,0,0
- •Invoke TranslateMessage, addr msg
- •Invoke DispatchMessage, addr msg
- •Invoke PostQuitMessage,null
- •Invoke DefWindowProc,hWnd,uMsg,wParam,lParam
- •Хід роботи:
- •Контрольні питання:
- •Лабораторна робота n 3
- •Теоретичні відомості.
- •Invoke BeginPaint,hWnd, addr ps
- •Invoke GetClientRect,hWnd, addr rect
- •Invoke EndPaint,hWnd, addr ps
- •Лабораторна робота n 4
- •Теоретичні відомості.
- •Invoke InvalidateRect, hWnd,null,true
- •Хід роботи:
- •Контрольні питання:
- •Характеристика повідомлень, що посилають від клавіатури.
- •Лабораторна робота n 5
- •Теоретичні відомості.
- •Invoke lstrlen,addr AppName
- •Invoke TextOut,hdc,hitpoint.X,hitpoint.Y,addr AppName,eax
- •Хід роботи:
- •Контрольні питання:
- •Лабораторна робота n 6
- •Теоретичні відомості.
- •Invoke LoadMenu, hInst, offset MenuName
- •Invoke LoadMenu, hInst, offset MenuName
- •Хід роботи:
- •Контрольні питання:
2. Програмні сегменти
Розглянуті угоди про сегментні регістри змушують нас у такий спосіб будувати програму: в одному сегменті пам'яті треба розмістити всі команди програми й установити регістр CS на початок цього сегмента, в іншому сегменті треба розмістити всі дані програми й на його початок установити регістр DS, а третій сегмент треба відвести під стек і встановити на його початок регістр SS. Але пропозиції нашої програми на мові А розміщає в пам'яті асемблер, а не ми. Як же асемблер визначає, які пропозиції в якому сегменті розміщати? Відповідь такої: він цього не знає, це повинні повідомити йому ми самі. І робиться це так: всі пропозиції, які ми хочемо розмістити в одному сегменті пам'яті, ми зобов'язані в тексті програми об'єднати в так званий програмний сегмент. Це аналог сегмента пам'яті, але в термінах мови А. Програмний сегмент має наступну структуру:
<ім'я сегмента> SEGMENT <параметри> <пропозиція>
<пропозиція> <ім'я сегмента> ENDS
Програмному сегменту дається ім'я, що повинне бути повторене двічі -у директиві SEGMENT, що відкриває сегмент, і в директиві ENDS (end of segment), що закриває його. Між цими директивами може бути зазначене будь-яке число будь-яких пропозицій. Зміст всієї цієї конструкції такий: ми заявляємо асемблеру, що всі пропозиції між директивами SEGMENT і ENDS він повинен розмістити в одному сегменті пам'яті. Але при цьому треба пам'ятати, що розмір сегмента пам'яті не повинен перевищувати 64 Кб, тому зазначених пропозицій повинне бути стільки, щоб у сукупності вони займали не більше 64 Кб, інакше асемблер зафіксує помилку.
Відзначимо, що в програмі може бути кілька сегментів з тим самим ім'ям. Уважається, що це один сегмент, просто він з якоїсь причини описаний вроздріб; всі пропозиції цих частин асемблер з'єднає разом.
Параметри директиви SEGMENT будуть розглянуті пізніше, а поки лише відзначимо, що параметри в основному потрібні тоді, коли програма більша й зберігається в декількох файлах, і параметри вказують, як поєднувати ці файли. Якщо ж програма невелика, уміщається в одному файлі, тоді параметри не потрібні.
Приклад програмних сегментів:
A SEGMENT
Al DB 400h DUP(?)
А2 DH 8
A ENDS
В SEGMENT
B1 DW A2
В2 DD A2
В ENDS
З SEGMENT
ASSUME ES:A, DS:B, CS:C
L: MOV AX,A2
MOV BX,B2
З ENDS
Використовуючи цей приклад, уточнимо деякі речі.
У загальному випадку асемблер розміщає в пам'яті програмні сегменти послідовно один за одним, причому кожний з них він обов'язково розміщає з адреси, кратного 16, - із границі так званого параграфа (параграфом у ПК називають ділянка пам'яті, що починається з адреси, кратного 16, і складається з 16 байтів). Нехай, наприклад, сегмент А розміщений з абсолютної адреси l0000h. Тоді всі пропозиції цього сегмента займуть у пам'яті байти з адресами від l0000h до 10401h. Після цього перший вільний байт буде мати адреса 10402h. Він не кратний 16 (не кінчається на 0) і з його не можна розміщати сегмент В, тому асемблер пропускає цей і наступні байти аж до найближчого байта з адресою, кратною 16. Це адреса 10410h. З його асемблер і почне: розміщення пропозицій сегмента В, зайнявши під них 6 байтів. Сегмент Із буде розміщений з наступної адреси, кратного 16, тобто з 10420h. Таким чином, асемблер сам стежить за тим, щоб сегменти розміщалися в пам'яті з адрес), кратних 16, рятуючи нас від цієї турботи.
