
Завдання
Скласти шаблон ЕХЕ-программьі під ім'ям FRAME.ASM з певним набором і порядком опису сегментів, перевірити його працездатність. На основі шаблону створити окрему програму SURNAME.ASM: визначити в сегменті даних ASCII$-CTpoKy зі своїм прізвищем і вивести її на екран функцією 9 DOS. Якщо в шаблоні за завданням сегменту даних немає, вважати, що він співпадає з сегментом команд і описати рядок в сегменті команд.
Варіанти наборів сегментів:
Команд, даних, стека.
Даних, команд.
Стека, даних, команд.
Команд, стека, даних.
Даних, команд, стека.
Стека, команд, даних.
Команд, даних.
Стека, команд (рядок — на початку).
Команд (рядок — в кінці), стека.
Команд (рядок — на початку).
Стека, команд (рядок — в кінці).
Команд (рядок — на початку), стека.
Команд (рядок — в кінці).
14. Даних, стека, команд.
Лабораторна робота №2
Дослідження циклічних алгоритмів для формування та виводу на екран ASCII кодованих символів.Теоретичні відомості
Використання сервісних підпрограм. Одним з основних засобів, що є у розпорядженні системного програміста, є набір службових підпрограм базової системи введення-виводу (BIOS) і операційної системи (ОС). їх використання позбавляє від необхідності настроюватися на роботу кожного конкретного пристрою, розробляти кожного разу наново службові базові процедури і, оскільки ці підпрограми є стандартними, підвищує сумісність програм.
У DOS доступ до службових підпрограм (їх називають функціями) здійснюється за допомогою програмних переривань, що викликаються по команді INT. Як огіеранд цієї команди указується номер переривання.
Всього є 256 номерів, частина з них не використовується. Підпрограм значно більше, тому їх групують і призначають номер переривання цілій групі. При виклику переривання уточнюють, до якої підпрограми потрібно звернутися. Найчастіше для цього використовують регістр АН — в нього заносять безпосередньо перед викликом переривання номер функції. Приклад виклику 1-ої функції переривання 21h:
mov ah, 1
int 21h
В результаті виконання команди INT управління передається програмі обробки відповідного переривання (в даному випадку 21h); після закінчення роботи управління повертається в перервапу програму.
Багато функцій потребують певних вхідних даних, що визначають результат її роботи. Регістри, через які ці дані передаються, називаються вхідними. Також функція може повертати певний результат — у вихідних регістрах. Таким чином, в загальному випадку процедуру виклику N-й функції переривання X можна записати так:
;заповнення вхідних регістрів
mov ah, N ;АН = номер
функції
int X ;вызов переривання
X
/аналіз вихідних регістрів
По номеру переривання можна визначити, чи відноситься дана підпрограма до BIOS, DOS або є призначеною для користувача.
Більшість службових підпрограм DOS зведені в переривання 21h. Серед них — функції для введення з клавіатури і виводу на екран, функції роботи з файлами, управління пам'яттю і процесами та інші. Інформацію про номери функцій і переривань, вхідні і вихідні регістри, а також опис дії функцій можна знайти в довідниках по MS-DOS.
У лабораторній роботі 1 нами викликалися дві функції: 9 — виведення ASCII$-CTpoKH на екран, і 4Ch — завершення роботи програми. Функція 4Ch є виключенням з правила: після закінчення її роботи управління повертається не програмі, що викликала, а батьківському процесу, що запустив програму (наприклад, командному інтерпретатору).
Вивід на екран. У DOS є стандартні функції виведення символьних даних: 2, 6, 9 і 40h. Нижче приводиться їх опис:
к> у АН |
Опис |
Вхід |
Вихід |
2 h |
Виведення символу в БТБОиТ |
DL ASCII-код символу |
|
6 h |
Виведення символу в ЗТБОиТ |
DL ASCIІ-код символу (окрім OFFh) |
_ |
9 h |
Виведення АБСІІ$-строки в БТБОиТ |
DS:DX ASCII$-CTpOKy |
— |
4 Oh |
Виведення АБСІ12-строки на пристрій або у файл |
DS: DX ASCIIZ-строку; CX довжина рядка в байтах; ВХ - № пристрою/файлу (1 ДЛЯ STDOUT) |
СЕ = 0 при отсутствии помилок; АХ = число записаних байт |
Стандартним пристроєм виведення STDOUT в більшості випадків є екран, проте можна перенаправляти вивід, тобто як STDOUT використовувати інший пристрій або файл (наприклад, команда tasm > options.Ist перенаправить список опцій запуску, що виводиться асемблером, у файл options.Ist).
Цикли. Цикли в програмах на асемблері реалізуються за допомогою команд передачі управління JMP (безумовний перехід), Jxx (умовний перехід) і LOOP ("петливши").
За допомогою команди JMP можна здійснювати переходи назад (так можуть створюватися нескінченні цикли):
metka:
... ; (тілс циклу)
jmp metka ; перехід назад
або переходи вперед (обхід певної ділянки програми):
jmp metka ; перехід вперед
metka:
Часто в тіло циклу поміщають команду умовного переходу для забезпечення можливості виходу з циклу (або передбачають можливість переривання виконання тіла циклу по натисненню CTRL-C або Ctrl-Break).
Команд умовного переходу Jxx декілька (замість хх указується символ або набір символів, що визначають умову переходу). Як і в команді JMP, як операнд указується мітка переходу, і ця мітка може указуватися як до команди переходу (перехід назад), так і після (перехід вперед).
Більшість з команд умовних переходів передають управління на вказану мітку залежно від стану прапорів процесора. Наприклад, команда JZ metka передає управління на мітку metka, якщо встановлений прапор нуля (Jump if Zero, ZF=1), JC — якщо встановлений прапор перенесення (Jump if Carry, CF = 1), a JS — якщо встановлений прапор знаку (Jump if Sign, SF = 1) і т. д. Якщо ж відповідний прапор скинутий, управління передається на наступну після Jxx команду. Також є команди, передавальні управління на вказану мітку, якщо відповідний прапор скинутий (JNZ — Jump if Not Zero, ZF = 0; JNC — Jump if No Carry, CF = 0 і т, д.).
Щоб користуватися такими командами, необхідно знати, в якому стані може знаходитися певний прапор і які команди впливають на його стан. Часто застосовують схему використання команд умовного переходу, при якій немає необхідності стежити за прапорами. Ось ця схема у вигляді фрагмента коди і блок-схеми:
metka:
cmp jxx
Команда CMP (Compare) проводить порівняння операндів (за допомогою
віднімання другого з першого) і відповідно до результату
порівняння формує
прапори (так само, як і команда звичайного віднімання SUB). При цьому в мнемонічному позначенні команд переходу указується не
(переход ПО
операцді, оішранд2 metka
(проверка
прапор, що перевіряються, а результат порівняння. Наприклад, команда JE передає управління на мітку, якщо порівнювані операнди були рівні (Jump if Equal), а команда JNE - якщо не рівні (Jump if Not Equal). (Якщо порівнювані командою CMP операнди рівні, то результат віднімання одного операнда з першого дасть нульовий результат і встановиться прапор нуля ZF. Команда JE перевірить цей прапор і передасть управління на мітку точно так, як і команда JZ. Насправді JZ і JE — різні позначення однієї машинної команди процесора, створені для зручності програмування).
Окрім команд JE (JNE) часто доводиться користуватися командами JA (Jump if Above — перехід, якщо вище), JB (Jump if Below — перехід, якщо нижче), JG (Jump if Greater — перехід, якщо більше), JL (Jump if Less — перехід, якщо менше) і їх антиподами JNA, JNB, JNG і JNL відповідно. Поняття "вище" і "нижче" відносяться до порівняння беззнакових операндів, а "більше" і "менше" — знакових (у додатковому коді).
Цикл з передумовою організовується вказівкою команди Jxx на початку JMP-цикла, з умовою поста — в кінці (у будь-якому випадку до мітки початку циклу повинна бути проинициализирована змінна циклу).
; Цикл з передумовою
raetka:
jxx exit
... ; (тіло циклу)
jmp raetka - .
exit:
; Цикл з умовою поста ,/ '
met ka: '
; (тіло циклу) і х \
jxx exit ''о^-ІМ I
■ і-. 'Огг *
jmp metka --/JJy \
exit: '"••Ч.. 1
■*. t і m
I Li: j
Цикл, організований тільки командою Jxx, — завжди цикл з умовою поста. Цей варіант циклу простіший, ніж організований за допомогою двох команд переходу.
Для утворення циклу команд умовного переходу часто немає необхідності вводити окрему змінну для лічильника циклу, оскільки вже є яка-небудь змінна (або навіть декілька), що циклічно міняє своє значення. Вихід з циклу можна здійснити після досягнення цієї
певного значення. Інакше йде справа з циклами, утвореними за допомогою команди LOOP. Ця команда спеціально призначена для організації циклів і завжди використовує регістр СХ як лічильник циклу.
Як операнд команди LOOP також указується мітка переходу. Команда LOOP зменшує значення регістра СХ на 1 і потім порівнює його з нулем. Якщо значення СХ не рівне 0, LOOP передає управління на вказану мітку, якщо рівно — управління передається на наступну за LOOP команду.
Перед початком циклу необхідно заповнити регістр СХ початковим значенням N (приклад нижчий). При цьому тіло цикл буде виконаний N разів, а команда LOOP передасть управління на мітку (N- 1) разів.
; Цикл, N разів, що повторюється mov сх, N
metka:
... ; (тіло циклу)
loop metka
Як ілюстрація розглянемо текст програми виводу на екран рядка ASCII-символов з кодами від 32 до 255 (коди 0-31 часто використовуються як керівники). Для заповнення області пам'яті використовуємо LOOP-цикл, а для виведення отриманої послідовності на екран - функцію виведення 40h int 21h. Використанню функції 9 в даному випадку перешкоджає наявність в рядку символу '$' (код 36), який інтерпретується функцією як ознака кінця рядка.
; Лістинг 2. Виведення рядка ASCII-символов на екран oursg segment
assume es:oursg, ds:oursg symb db 224 dup('*') ; резервуємо місце
(рядок) в пам'яті begin:
mov ах, oursg ; сегментна адреса
даних
mov ds, ах ; засилаємо в DS
; Заповнення рядка в пам'яті символами
mov сх/ 224 ; число повторень
циклу (256-32)
mov al, 32 ; починаємо з
пропуску (32)
mov si, 0 ; індекс усередині
відведеного рядка пам'яті
m: mov [symb+si], al ; пересилаємо
символ з AL в чергову позицію
; відведеного рядка, затираючи зірочку inc аі ; збільшуємо AL
(код символу) на 1
inc si ; і індекс наший
рядки (наступна позиція)
loop пі ; повтор
; Виведення рядка-результату на екран
mov ah, 40h ; номер функції
DOS зиведення рядка
mov сх, 224 ; довжина рядка,
що виводиться (у байтах)
mov bx, 1 ; 1 - вивід на
екран
mov dx, offset symb; відносна адреса
рядка, що виводиться
int 21h ; виклик DOS
; Завершення програми
mov ах, 4C00h ; AH = 4Ch, AL = 0
(код виходу)
int 21h
oursg ends
end begin
Для вказівки черговій позиції рядка в пам'яті використовувалася індексна адресація з регістром SI (можна було б також використовувати DI або ВХ). Вказану адресу почала рядки (symb) складається з вмістом регістра SI (індексування), результат розглядається як відносна адреса (offset), яка в сукупності з сегментною адресою (вміст регістра DS) дає повну адресу необхідного осередку.
Інший можливий варіант — використання непрямої адресації без зсуву, коли в регістр SI (DI або ВХ) поміщається адреса почала рядки, який потім так само в циклі збільшується на І:
mov [si], al ; засилаємо символ
в рядок
inc si
(Команда INC проводить збільшення операнда на 1. Для зменшення операнда на І служить команда DEC).