- •Лабораторна робота 1.
- •1. Символи.
- •2 Представлення чисел у пам’яті пеом.
- •2.1 Цілі числа. Цілі числа без знака
- •2.2 Цілі числа зі знаком
- •3 Дійсні числа.
- •3.1 Представлення дійсних чисел у двійковому нормалізованому виді.
- •3.2 Машинні формати дійсних чисел
- •3.2.1. Формат 32 біти - float (або single)
- •3.2.2. Формат 64 біти - double
- •4. Завдання на лабораторну роботу.
- •5. Методичні вказівки з оформлення звіту
- •6. Рішення типового прикладу (без оцінки похибки перетворення)
- •7. Питання для самоперевірки
- •8. Література
- •Лабораторна робота 2.
- •1. 3 Формати файлів, що виконуються, які підтримуються у fasm
- •2. Завдання на лабораторну роботу:
- •3. Методичні вказівки з оформлення звіту
- •4. Питання для самоперевірки.
- •Лабораторна робота 3.
- •1. Підготовка до роботи.
- •2. Питання для самоконтролю.
- •3. Короткі теоретичні відомості.
- •3.1 Команди пересилання даних.
- •3.1.3 Операції зі стеком:
- •3.2 Робота із налагоджувачем OllyDbg.
- •3.2.2. Розглянемо основні команди меню OllyDbg.
- •4. Завдання на лабораторну роботу.
- •9. Література
- •Лабораторна робота 4.
- •3.2. Операції із прапорами процесора:
- •3.3 Команди розповсюдження знаку
- •4. Методичні вказівки з оформлення звіту
- •5. Рішення типового прикладу.
- •6. Завдання на лабораторну роботу
- •7. Критерії оцінювання.
- •8. Питання для самоперевірки
- •9. Література
- •Лабораторна робота 5.
- •3.2. Команди зсуву
- •3.3 Команди сканування бітів
- •4. Методичні вказівки з оформлення звіту
- •5. Приклади використання бітових команд
- •6. Завдання на лабораторну роботу
- •7. Критерії оцінювання.
- •8. Питання для самоперевірки
- •9. Література
- •Лабораторна робота 6.
- •1. Підготовка до роботи.
- •2. Питання для самоконтролю.
- •3. Короткі теоретичні зведення.
- •3.1. Команди безумовної передачі управління
- •3.1.1. Команда безумовного переходу jmp
- •3.2. Команди умовної передачі управління Jcc
- •3.2.1. Перша група команд умовного переходу.
- •3.2.2 Друга група команд умовного переходу.
- •3.2.3. Третя група команд умовного переходу.
- •3.3. Команди управління циклами looPx
- •3.3.1. Команда loop — перехід по лічильнику
- •3.3.2. Команда loope (loopz) перехід по лічильнику і якщо дорівнює
- •3.3.3. Команда loopne (loopnz) перехід по лічильнику і якщо не дорівнює
- •4. Методичні вказівки з оформлення звіту
- •5. Приклади використання бітових команд
- •6. Завдання на лабораторну роботу.
- •7. Критерії оцінювання.
- •8. Питання для самоперевірки
- •9. Література
- •Лабораторна робота 7.
- •1. Підготовка до роботи.
- •2. Питання для самоконтролю.
- •3. Короткі теоретичні відомості.
- •3.1. Реалізація основних операцій по обробці масивів мовою асемблера.
- •4. Методичні вказівки з оформлення звіту
- •5. Критерії оцінювання.
- •6. Завдання на лабораторну роботу.
- •7. Питання для самоперевірки
- •8. Література
- •Лабораторна робота 8.
- •1. Підготовка до роботи.
- •2. Питання для самоконтролю.
- •3. Короткі теоретичні відомості.
- •4. Приклади виконання деяких типових задач обробки рядків
- •4. Завдання на лабораторну роботу.
- •Лабораторна робота 9.
- •1. Підготовка до роботи.
- •2. Питання для самоконтролеві.
- •3. Короткі теоретичні відомості
- •3.1. Принципи організації підпрограм
- •3.2. Параметри процедур і значення, що повертаються
- •3.3. Використання загальних перемінних у процедурах
- •3.4. Особливості fasm по організації підпрограм (Windows - додатка).
- •Лабораторна работа 10-11.
- •3.1.2. Засобу bios
- •3.2. Уведення з клавіатури
4. Приклади виконання деяких типових задач обробки рядків
Приклад 1. Пересилання і копіювання даних.
Для виконання операцій пересилання і копіювання рядків і масивів дуже зручно використовувати команду movs. Ця команда може застосовуватися для пересилання одиночних байтів, слів або подвійних слів, однак із префіксом rер і лічильником байтів у регістрі ЕСХ (СХ) можна виконувати пересилання будь-якого числа символів більш ефективно. При цьому в регістрі EDI (DI) повинний утримуватися відносна адреса області пам'яті, у яку буде поміщений рядок, а адресація джерела виконується через регістр ESI (SI).
Таким чином, перед виконанням команди movs варто ініціалізувати регістри ESI (SI) і EDI (DI) необхідними відносними адресами джерела і приймача. У залежності від стану прапора DF команда movs робить збільшення або зменшення на 1 (для байта), на 2 (для слова) і на 4 (для подвійного слова) умісту регістрів EDI (DI) і ESI (SI).
При використанні команди movs (b, w, d) компілятор асемблера припускає наявність коректного розміру строкових даних і не вимагає кодування операндів у команді. Для команди movs розмір повинний бути закодований в операндах. Наприклад, якщо перемінні STRING_A і STRING_B визначені як байтові за допомогою директиви DB, те наступна команда буде виконувати пересилання байтів, кількість яких визначене в регістрі СХ, з перемінної STRINGB у перемінну STRINGA:
rep movs STRING_A, STRING_B
Цю команду можна записати в альтернативній формі:
rep movs ES: BYTE PTR [DI], DS:[SI]
У будь-якому випадку перед початком операції варто помістити в регістри DI і SI адреси STRING_A і STRING_B.
Приклад виконання.
|
format pe |
|
start: |
cld |
; установимо прапор напрямку DF для інкременту |
|
lea esi, [src] |
; адреса джерела -> DS: SI |
|
lea edi, [dst] |
; адреса приймача -> ES: DI |
|
mov ecx, [len] |
; кількість символів, що копіюються -> CX |
|
rep movsb |
; копіювання символів |
|
mov edx, dst |
; адреса результуючого рядка |
|
ret |
|
|
|
; секція визначення даних |
|
src DB “COPIED TESTING STRING” len=$-src |
|
|
dst DB len DUP (' ') DB '$' |
Приклад 2. Порівняння рядків і масивів
Операція порівняння рядків і масивів може виконуватися як за допомогою звичайних команд асемблера, так і з використанням спеціальної ланцюжкової команди cmps. Команда cmps порівнює вміст однієї області пам'яті (яка адресується регістрами DS: SI або ESI) із вмістом іншої області пам'яті (яка адресується регістрами ES: DI або EDI). У залежності від значення прапора DF команда cmps також збільшує або зменшує адреси в регістрах ESI (SI) і EDI (DI) на 1 для байта, на 2 для слова і на 4 для подвійного слова. Команда cmps впливає на прапори AF, CF, OF, PF, SF і ZF. При використанні префікса rep регістр ЕСХ (СХ) повинний містити кількість порівнюваних перемінних, при цьому команда cmps може порівнювати будь-яке число байтів або слів.
При виконанні команди cmps (а також seas) можлива установка прапорів стану так, щоб операція могла завершитися відразу після виявлення необхідної умови.
При рішенні даної задачі необхідно визначити розмір порівнюваних рядків, а тільки потім – робити порівняння.
Приклад. Порівняння рядків по декількох критеріях
|
format pe |
|
start: |
|
|
|
mov esi, str1 |
; адреса рядка - джерела |
|
mov edx, esi |
|
|
mov eax, 0 |
|
src_again: |
|
|
|
cmp al, [esi] |
|
|
je check_dst |
|
|
inc esi |
|
|
jmp src_again |
|
check_dst: |
|
|
|
mov edi, str2 |
; адреса рядка - приймача |
|
mov ebx, edi |
|
dst_again: |
|
|
|
cmp al, [edi] |
|
|
je check_size |
|
|
inc edi |
|
|
jmp dst_again |
|
check_size: |
|
|
|
mov ecx, ESI |
|
|
sub ECX, EDX |
|
|
mov EAX, EDI |
|
|
sub EAX, EBX |
|
|
cmp EAX, ECX |
|
|
je compare |
|
|
lea EAX, [size_diff] |
|
|
jmp exit |
|
compare: |
|
|
|
cld |
|
|
mov ESI, EDX |
|
|
mov EDI, EBX |
|
|
repe cmpsb |
|
|
je equal |
|
|
lea EAX, [s_ne] |
|
|
jmp exit |
|
equal: |
|
|
|
lea EAX, [s_eq] |
|
exit: |
|
|
|
ret |
|
|
s_eq DB “Strings are equal”,0 |
|
|
s_ne DB “Strings are not equal”,0 |
|
|
size_diff DB “Strings have different size!",0 |
|
|
str1 db “1st string”,0 |
|
|
str2 db “1st string”,0 |
Приклад 3. Сканування рядків і масивів
У процесі обробки текстової інформації може виникнути необхідність маніпулювання елементами рядків або масивів. Найбільше часто виконуються такі операції:
• заміна визначених символів у тексті іншими, наприклад підстановка пробілів замість різних символів, що редагують, (табуляції, повернення каретки і перекладу рядка)
; підрахунок кількості елементів рядків або масивів, що задовольняють якій-небудь умові
; обробка окремого елемента масиву чисел, наприклад обчислення модуля числа, квадратного кореня і т. д.
Мова асемблера має широкі можливості для виконання таких операцій. Ми розглянемо різні способи сканування рядків і масивів і почнемо з використання спеціально призначеної для цього команди seas. Команда seas відрізняється від команди cmps тим, що виконує перегляд рядка або масиву в пошуку визначеного елемента. Команда seas порівнює вміст області пам'яті, яка адресується регістрами ES: DI або EDI, із умістом регістра AL, АХ або ЕАХ.
Операція порівняння здійснюється шляхом вирахування вмісту комірки пам'яті з умісту AL, АХ або ЕАХ, із установленням при цьому відповідних прапорів. У залежності від значення прапора DF команда seas збільшує або зменшує адресу в регістрі DI (EDI) на 1 для байта, на 2 для слова і на 4 для подвійного слова. Команда seas установлює прапори AF, CF, OF, PF, SF і ZF. При використанні префікса rep і розміру рядка в регістрі СХ (ЕСХ) команда seas може сканувати рядки і масиви будь-якого розміру. Ця команда особливо корисна при розробці текстових редакторів, де програма повинна сканувати рядка, виконуючи пошук знаків пунктуації.
Приклад. Пошук і заміна чисел менше заданого в масиві цілих чисел. Даний приклад ілюструє можливості ланцюжкових команд по обробці масивів чисел.
|
format pe |
|
|
mov ECX,??? |
; размер массива -> ECX |
|
mov EDI,??? |
; адреса першого елемента-> EDI |
|
mov EAX,??? |
; порівнюване значення |
|
cld |
; установити прапор напрямку |
|
|
; убік збільшення адрес |
next: |
|
|
|
scasd |
; порівнюємо елементи масиву |
|
|
; із умістом EAX |
|
jg change |
; число в EAX більше |
|
|
; поточного елемента? |
|
loop next |
|
|
jmp exit |
|
change: |
|
елемент масиву менше |
|
|
; числа в EAX |
|
mov dword [EDI-4], 0 |
; замінити вміст осередку |
|
|
; пам'яті на 0 |
|
dec ECX |
; декремент лічильника |
|
jmp next |
|
exit: |
|
|
|
ret |
|
|
|
; тут задаємо масив |
Приклад 4. Використання команд lods і stos
Команда lods може завантажити з пам'яті один байт у регістр AL, одне слово в регістр АХ або одне подвійне слово в регістр ЕАХ. Адреса пам'яті визначається або регістрами DS: SI, або регістром ESI. Як і для попередніх ланцюжкових команд, у залежності від значення прапора DF відбувається інкремент або декремент умісту регістра SI або ESI. Ця команда використовується без префікса повторення rep.
Якщо порівнювати команди mov і lods, то при однаковому результаті mov вимагає трьох байтів машинного коду, у той час як lods — тільки одного. Команда lods додатково вимагає ініціалізації регістра SI або ESI. Команда lods зручна в тих випадках, коли потрібно аналізувати кожен байт, слово або подвійне слово і виконувати з ними визначені дії. Команда 1ods підійде, наприклад, при заміні окремих символів рядка, для реверсування рядка, тобто зміни порядку проходження елементів на зворотний, і т. д. Команда lods, як і інші ланцюжкові команди, має модифікації для роботи з байтами (lodsb), зі словами (lodsw) і подвійними словами (lodsd).
Команда stos записує вміст одного з регістрів AL, АХ або ЕАХ у байт, слово або подвійне слово в пам'яті. Адреса пам'яті визначається регістрами ES: DI або регістром EDI. У залежності від значення прапора DF команда stos збільшує або зменшує адресу в регістрі DI на 1 для байта, на 2 для слова і на 4 для подвійного слова. Команда stos, використовувана з префіксом rep, дозволяє ініціалізувати область даних якими-небудь значеннями, наприклад пробілами або нулями. Команда stos, як і інші ланцюжкові команди, має модифікації для роботи з байтами (stosb), зі словами (stosw) і подвійними словами (stosd).
Приклад. Підрахунок числа символів у рядку
|
format pe |
|
start: |
|
|
|
lea esi, [src] |
|
|
mov ecx, len |
|
|
cld |
|
|
xor ebx, ebx |
|
next: |
|
|
|
lodsb |
|
|
cmp al, 's' |
|
|
sete bl |
; див. примітку |
|
add [cnt], ebx |
|
|
loop next |
|
|
lea eax, [cnt] |
|
|
ret |
|
|
cnt dd 0 |
|
|
src db “this string contains five words”,0 |
|
|
len = $-src-1 |
|
Примітка: інструкції, утворені за допомогою додавання умовного мнемоніка) до мнемоніку set привласнюють байтові одиницю, якщо умова щира, і нуль, якщо умова не виконується, див. лабораторну роботу №4 “Команди передачі керування”.
Операндом повинний бути 8-бітний регістр загального призначення або байт у пам'яті.
setne al ; одиницю в al, якщо прапор нуля порожній
seto byte [bx] ; одиницю в байт, якщо є переповнення
Приклад 5. Масиви рядків
У багатьох випадках програмістові приходиться мати справа не з окремими рядками, а з групою, або масивом, рядків. Дуже часто в програмах потрібно, у залежності від результатів якихось проміжних обчислень, відображати відповідну інформацію, що утримується в одній з рядків масиву.
Процедура приймає як параметр номер рядка, рівний 0,1 або 2, і повертає адреса обраної раніше рядка. Як індексатор рядка обраний регістр ЕСХ, у якому отриманий номер рядка збільшується на 4 (адреса рядка представлена подвійним словом). У регістр ESI міститься адреса масиву рядків (він збігається з адресою подвійного слова, що містить адресу нульового рядка). Для доступу до подвійного слова, що містить адресу необхідного рядка, випливає до вмісту ESI додати вміст регістра ЕСХ. Нарешті, у регістр ЕАХ міститься адреса шуканого рядка.
Приклад.
|
format pe |
|
|
jmp start |
|
|
s1 DB “It's a String s1”,0 |
|
|
s2 DB “Here is String s2”,0 |
|
|
s3 DB “String s3 is placed here”,0 |
|
|
label saddr dword |
|
|
DD s1 |
|
|
DD s2 |
|
|
DD s3 |
|
start: |
|
|
|
mov ECX,???? |
; індекс рядка -> ECX |
|
shl ECX, 2 |
; перетворити в подвійне слово |
|
lea ESI, [saddr] |
; адреса масиву рядків saddr –> ESI |
|
add ESI, ECX |
; адреса подвійного слова, що містить |
|
|
; адреса рядка -> ESI |
|
mov EAX, [ESI] |
; адреса шуканого рядка -> EAX |
|
ret |
|