Функции dos int 20h завершить программу


Содержание

Функции dos int 20h: завершить программу

Это прерывание используется для выхода из программы и возврата управления родительскому процессу (обычно интерпретатору команд DOS — COMMAND.COM). Оно восстанавливает значения управляющих векторов INT 22h, INT 23h и INT 24h. Оно также сбрасывает все файловые буфера (если длина файла изменилась, то файл должен быть предварительно закрыт).

Важно:
Регистр CS должен содержать значение PSP завершающегося процесса. Если ваш CS не равен PSP, вы можете выдать JMP или RET на PSP:0000. Рекомендуется использовать функцию 4cH Terminate, чтобы избежать трудностей, связанных с неравенством CS и PSP. Она позволяет также задать код выхода. Программы COM-формата обычно выполняются при CS=PSP, так что им можно выдавать INT 20h в любой момент. EXE-программы могут выдавать FAR JMP или FAR RET, чтобы передать управление на PSP:0000, где содержится инструкция INT 20h.

Операционная система MS-DOS

1.5. Обзор прерываний DOS

DOS предоставляет программе набор системных вызовов, реализованных с использованием механизма программных прерываний. Эти вызовы открывают прикладной программе доступ к системной информации, к системе консольного ввода/вывода, файловой системе, к подсистеме управления программами и памятью, позволяют организовать обращение к драйверам устройств ввода/вывода и т.д.

Все основные функции DOS вызываются с помощью прерывания INT 21h, однако DOS использует и другие прерывания:

INT 20h завершение работы программы;
INT 25h/26h чтение/запись на диск с абсолютной адресацией секторов;
INT 27h завершение работы программы с оставлением ее резидентной в памяти;
INT 28h прерывание зарезервировано для DOS, может быть использовано для составления резидентных программ;
INT 2Eh выполнение команды DOS;
INT 2Fh прерывание мультиплексора, используется для спулера печати PRINT.COM.

Функции прерывания INT 21h можно разделить на следующие группы:

  • получение системной информации;
  • символьный ввод/вывод;
  • работа с файловой системой;
  • управление программами;
  • управление памятью;
  • связь с драйверами устройств;
  • прочий системный сервис.

В данном обзоре мы кратко рассмотрим эти группы, делая акцент в основном на составе функций. Полностью информация об использовании функций прерывания DOS INT 21h (и других прерываний DOS) будет приводиться в соответствующих разделах книги.

Номер функции задается при вызове прерывания INT 21h в регистре AH.

Получение системной информации.

Функция 30h возвращает в регистре AX номер версии DOS. Например, для версии MS-DOS 5.00 содержимое регистра AH равно 00, регистра AL — 05.

Дополнительно через регистр BH функция возвращает программе серийный номер фирмы-производителя ОЕМ (IBM — 00, DEC — 16h, 0FFh — Microsoft и т.п.), а в регистрах BL:CX после вызова функции находится серийный номер пользователя.

Эта информация может применяться для анализа возможности использования таких средств операционной системы, которые поддерживаются не всеми версиями DOS, или для настройки программы на конкретный серийный номер пользователя.

Функции 2Ah и 2Ch позволяют программе узнать системную дату и время.

Есть функции, возвращающие текущий диск и текущий каталог. Номера этих функций — 19h и 47h.

Функция 2Fh позволяет программе узнать адрес текущей области DTA (Disk Transfer Area). Эта область используется, например, при поиске файлов в каталоге.

Важная информация находится в блоке PSP (Programm Segment Prefix). Этот блок располагается в памяти непосредственно перед выполняющейся программой. В нем находятся, в частности, параметры, передаваемые программе при запуске. Функция 62h возвращает адрес текущего блока PSP.

Кратко перечислим некоторые другие функции для получения системной информации:

35h получить значение вектора прерывания с заданным номером;
4Dh узнать код завершения процесса;
59h получить расширенный код ошибки;
54h узнать, используется ли проверка при записи на диск;
33h узнать, используется ли проверка на CTRL-BREAK.

Символьный ввод/вывод.

Эти функции применяются для работы со всеми символьными устройствами, такими как консоль, принтер, последовательный порт, и называются функциями стандартного ввода/вывода.

Ввод/вывод программы, использующей стандартные функции, может быть переназначен.

Приведем обзор основных функций стандартного символьного ввода/вывод в виде таблицы:

Код Назначение Описание
01h Ввод с клавиатуры Выполняется ввод символа со стандартного ввода и эхо-вывод символа на стандартное устройство вывода. Выполняется проверка на нажатие комбинации клавиш CTRL/C и CTRL-BREAK
06h Ввод с клавиатуры Ввод символа со стандартного ввода без ожидания и вывод его на устройство стандартного вывода. Комбинации CTRL/C и CTRL-BREAK не проверяются.
07h Прямой ввод Ввод символа со стандартного с клавиатуры устройства ввода. Комбинации клавиш CTRL/C и CTRL-BREAK не проверяются.
08h Ввод с клавиатуры Аналогично функции 07h, но проверяются комбинации клавиш CTRL/C и CTRL-BREAK.
02h Отобразить символ Отображаемый символ посылается на стандартное устройство вывода.
09h Отобразить строку На стандартное устройство вывода символов посылается строка, закрытая символом ‘$’.
03h Ввод из последовательного порта Вводится символ из последовательного порта
04h Вывод в последовательный порт Выводится символ на последовательный порт
05h Вывод на принтер Выводится символ на принтер.

Из таблицы видно, что для ввода с клавиатуры можно использовать несколько функций. Ввод без эхо-вывода удобен для такой информации, как пароли. Если логика работы программы не допускает прерывания по нажатию комбинаций клавиш CTRL-C или CTRL-BREAK, нужно использовать функции, которые не проверяют эти комбинации.

Для вывода строки символов можно использовать функцию 09h, но выводимая строка не может содержать символ ‘$’, так как этот символ используется в качестве признака конца строки.

Работа с файловой системой.

DOS предоставляет программам обширный сервис для работы с файлами и дисками. Практически все файловые операции можно выполнять с помощью специально предназначенных для этого функций, только в некоторых случаях (защита данных от копирования, например) приходится использовать прямое обращение к диску.

С помощью файловых функций DOS можно создавать и удалять файлы и каталоги, открывать и закрывать файлы, создавать временные файлы. Ввод/вывод может быть буферизован, можно получить как последовательный доступ к содержимому файла, так и произвольный.

Мы не будем приводить сейчас конкретные примеры или номера функций, отложим это до книги 3, посвященной файловой системе.

Управление программами.

DOS предоставляет программам возможность организовать запуск других программ или загрузку и выполнение программных оверлеев. Для этого служит функция 4Bh.

Для завершения работы программа должна также использовать одну из специальных функций DOS. Функция 4Ch, завершая работу программы, позволяет передать операционной системе некоторое число, называемое кодом завершения программы. Это число может быть затем проанализировано в пакетном файле командой IF ERRORLEVEL. Если одна программа запускает другую, то первая может получить код завершения второй с помощью функции 4Dh.

Для того чтобы завершающаяся программа осталась в оперативной памяти (т.е. стала резидентной), она должна вызвать прерывание INT 27h или воспользоваться функцией 31h.

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

Управление памятью.


DOS управляет распределением памяти с помощью блоков управления памятью MCB (Memory Control Block). Вся память разбивается на блоки различного размера, которым предшествует блок MCB, содержащий характеристики данного блока памяти (например, его размер).

Программа может динамически получать и освобождать области памяти с помощью функций 48h и 49h соответственно. Кроме того, можно изменять размер блока, выделенного операционной системой программе. Это делает функция 4Ah.

Детально механизм управления памятью будет рассмотрен в главе 2 при описании векторной таблицы связи DOS.

Связь с драйверами устройств.

Мы уже обращали Ваше внимание на то, что программы не могут обращаться непосредственно к драйверам устройств ввода/вывода. Все обращения к драйверам имеют либо неявный характер (ввод/вывод с помощью функций прерывания INT 21h), либо используют специальную функцию DOS с кодом 44h. Эта функция используется для обмена управляющей информацией между драйвером и программой.

Другие функции.

Существуют функции, позволяющие переопределять прерывания, работать с системными часами и календарем, функции для работы в сети и некоторые другие. Эти функции будут описаны позже в соответствующих разделах книги.

Функции dos int 20h: завершить программу

В данной статье рассматривается способ построения резидентных программ — TSR (Terminate and Stay Resident), позволяющий использовать область PSP (Program Segment Prefix) для размещения резидентного кода программы.

Несколько слов о TSR.

При разработке TSR — программ стандартными средствами DOS в памяти после завершения программы остается PSP размером 256 байт или по крайней мере его часть, если программа использует область FCB (File Control Block) и параметров для собственных нужд. Мы расскажем Вам о способе, позволяющем полностью использовать область PSP в интересах резидентной программы и приведем пример такой программы. Данный способ был разработан авторами в начале 1989 года, когда потребовалось загрузить много крохотных TSR — программ, размер которых не превышал PSP.

Кое-что о недокументированных функциях DOS.

Для понимания механизма разработки TSR без PSP необходимо ознакомиться с некоторыми недокументированными функциями DOS и с форматами PSP и MCB — Memory Control Block.

PSP — program segment prefix.

PSP всегда строится DOS при запуске любой программы и непосредственно предшествует началу программы. Рассмотрим формат PSP.

00h 2 БАЙТА содержит команду INT 20h, которая используется для завершения программы 02h СЛОВО сегментный адрес свободной памяти, следующей, за памятью, выделенной программе. Это может быть либо адрес за памятью DOS (например, A000h), либо адрес следующего доступного MCB. 04h БАЙТ Резерв 05h 5 БАЙТ длинный вызов диспетчера функций DOS. Содержит команду длинного перехода к диспетчеру функций DOS. Используется в программах, ориентированных на CP/M. Смещение в команде длинного перехода
содержит количество байтов, доступных в сегменте кода программы. 0Ah ДВ.СЛОВО копия вектора прерывания 22h, по которому управление передается для
завершения программы. 0Eh ДВ.СЛОВО копия вектора прерывания 23h, по которому управление передается при нажатии CONTROL-BREAK или CONTROL-C. 12h ДВ.СЛОВО копия вектора прерывания 24h, по которому управление передается при обнаружении критической ошибки. 16h СЛОВО сегментный адрес PSP родительского процесса (адрес текущего PSP для процесса, у которого нет родителя). 18h 20 БАЙТ FILE HANDLE TABLE. Содержит 20 однобайтовых индексов для системной таблицы файлов. Первые пять входов предназначены для STDIN, STDOUT,STDERR, AUXIO и LSTOUT. 2Ch СЛОВО сегментный адрес блока среды для процесса. 2Eh ДВ.СЛОВО область сохранения указателя стека процесса, когда процесс использует стек DOS (т.е. содержимое SS:SP перед последним подключением функции DOS с помощью INT 21h). 32h СЛОВО максимальное количество входов в FILE HANDLE TABLE (по умолчанию 20). 34h ДВ.СЛОВО адрес FILE HANDLE TABLE (стандартно указывает на таблицу в текущем PSP). 38h 24 БАЙТА Резерв 50h 3 БАЙТА команда INT 21h, за которой следует команда far RET. Используется для вызова диспетчера функций DOS. 53h 2 БАЙТА Резерв 55h 7 БАЙТ расширение первого FCB. 5Ch 16 БАЙТ начальные байты первого неоткрытого FCB. Открытие данного FCB приведет к разрушению второго FCB и байта с длиной командной строки. 6Ch 16 БАЙТ начальные байты второго неоткрытого FCB. Открытие данного FCB приведет к разрушению командной строки. 7Сh ДВ.СЛОВО Резерв 80h 128 БАЙТ область DTA (Data Transfer Area) по умолчанию. Перекрывает байт с длиной командной строки и буфер командной строки (127 байтов).

Размер блока — 256 байт.

MCB — memory control block.

MCB является блоком DOS описывающим каждый распределенный участок памяти. Как правило MCB всегда строится перед PSP исполняемой программы. Рассмотрим формат MCB.

00h БАЙТ тип блока:
‘M’ (4Dh) — промежуточный блок;
‘Z’ (5Ah) — последний блок. 01h СЛОВО сегмент владельца блока, 0 — свободный блок. 03h СЛОВО количество параграфов в блоке. 05h 11 БАЙТ Резерв

Размер блока — 16 байт.

Недокументированные функции DOS.

Рассмотрим теперь недокументированные функции DOS, которые используются для построения TSR без PSP.

установить текущий PSP.

Данная функция указывает DOS, что в качестве текущего следует использовать указанный PSP.

AH = 50h
BX = сегментный адрес нового PSP.

создать подчиненный PSP.

Данная функция требует от DOS создать подчиненный PSP. В отличии от функции 26h данные не копируются из текущего PSP, а строятся заново.

AH = 55h
BX = сегментный адрес для построения нового PSP.
SI = значение, которое требуется установить в поле со смещением 2 в новом PSP.

Процесс завершения резидентной программы.

Сущность завершения резидентной программы без PSP состоит в создании нового PSP и указании DOS использовать этот PSP в качестве активного. При этом сам текст резидентной части перемещается на начало старого PSP.

Рассмотрим последовательность действий при завершении программы.

  1. Освободить ENVIRONMENT, адрес которого находится в PSP по смещению 2Ch. Вообще говоря, это действие не связано с собственно процессом завершения резидентной программы без PSP и рекомендуется для любого способа завершения резидентных программ.
  2. Изменить размер памяти, используемый программой, указав в качестве нового размера длину резидентной части программы в параграфах, а в качестве адреса модифицируемой памяти — сегментный адрес PSP. Для выполнения используется функция DOS 4Ah. Если резидентная часть начинается с начала программы, то ее следует сначала сохранить, т.к. при освобождении памяти в теле программы будет построен новый MCB. Также целесообразно зарезервировать после резидентной части участок длиной 16 байт для MCB, чтобы последующие действия не уничтожили дальнейший код программы.
  3. Вычисляется сегментный адрес для построения нового PSP по формуле + +1 (размер MCB в параграфах).
  4. Строится новый PSP по вычисленному сегментному адресу с использованием функции 55h. В качестве значения SI берется поле со смещением 2 в старом PSP.
  5. Корректируется адрес родительского PSP в новом PSP по смещению 16h. Значение выбирается из поля с таким же смещением из старого PSP.
  6. Новый PSP указывается DOS в качестве текущего с использованием функции 50h.
  7. Корректируется указатель на собственника памяти в новом MCB по смещению 01h. MCB расположен по сегментному адресу равному сегменту нового PSP минус 1. Значение
    указателя устанавливается равным сегментному адресу нового PSP.
  8. Резидентная часть программы пересылается по адресу сегмента старого PSP со смещением 0.
  9. Выполняются необходимые действия для настройки резидентной части. Их можно также выполнить заранее.
  10. Программа завершается обычным образом по функции DOS 04Ch.
Илон Маск рекомендует:  Что такое код data mining

Схематически этот метод изображен на 3-х рисунках.

Рисунок 1 показывает изменение в расположении блоков в памяти при выполнении функции DOS 4Ah.

Рисунок 2 показывает изменение в расположении блоков в памяти после выполнения функции DOS 55h и при коррекции указателей.

Рисунок 3 показывает изменение в расположении блоков в памяти после выполнения функции DOS 50h.

Совместимость.


Данный метод опробован в различных совместимых операционных средах:

— MS/PC DOS 3.30;
— MS/PC DOS 4;
— MS DOS 5 beta release;
— DR DOS 3.41;
— DR DOS 5;
— с использованием загрузчика LOADHI от системы QEMM 5.0;
— с использованием загрузки в старшую память HILOAD DR DOS 5.

Пример резидентной программы без PSP.

Для лучшего понимания порядка завершения резидентной программы без PSP приведем пример.

page 60,132
title NONPSP — Резидентная программа без PSP
;==========================================================
;
; Пример построения резидентной программы без PSP
;
; Авторские права ГРУППЫ ПРОГРАММИСТОВ 2B
;
; Язык программирования: Ассемблер
; Транслятор : MASM
;
;===========================================================
;
; сообщить транслятору адресацию
;
assume cs:code,ds:code,es:nothing
;
; определить сегмент кода
;
code segment para
;
subttl Резидентная часть программы
;
ResStart label byte ;определим начало программы

;Текст резидентной части.

ResEnd label byte ;конец резидентной части
ResLen equ ResEnd-ResStart ;размер резидентной части в
; байтах
ResSize equ (ResEnd-ResStart+15)/16 ;размер резидентной
; части в параграфах
org ResStart+ResSize*16 ;для выравнивания на
; границу параграфа
;
page
subttl Инициализация резидентной программы без PSP
;
MCBLen equ 10h ;размер MCB
;
PSPMCB db MCBlen dup (0) ;резервная область для MCB
SavRes db ResLen dup (0) ;область сохранения
; резидентной части
;
PspOld dw 0 ;для адреса старого PSP
PspNew dw 0 ;для адреса нового PSP
;
; сообщения
;
MsgInst label byte
db 0ah,0dh
db ‘Программа установлена’
db 0ah,0dh
db ‘$’
MsgNoInst label byte
db 0ah,0dh
db ‘Ошибка. Программа не установлена’
db 0ah,0dh
db ‘$’
;=========================================================
;
; процедура инициализации резидентной программы без PSP
;
;=========================================================
ini proc far
;
cld ;для операций
пересылки
mov cs:PspOld,ds ;сохраним старый PSP
;
; Освобождение environment
;
mov ax,ds:[2ch] ;адрес сегмента
mov es,ax ; environment
cmp ax,0 ;есть environment ?
je Go1 ; нет
mov ah,49h ;код функции
int 21h ; освободить
; память
jnc Go1 ;успешно
jmp ErrorRet ;неуспешно
Go1:
mov word ptr ds:[2ch],0 ;укажем, что нет
; environment
push cs ;установим
pop es ; ES
push cs ;установим
pop ds ; DS
;
; запомним резидентную часть
; т.к. она будет разрушена при построении новых PSP и MCB
;
mov si,Offset ResStart ;откуда
mov di,Offset SavRes ;куда
mov cx,ResLen ;сколько
rep movsb ;перешлем
;
; модифицируем размер памяти текущей программы от сегмента
; PSP на длину резидентной части
; это приведет к построению нового MCB в теле программы
;
mov ah,4ah ;модифицируем память
mov bx,ResSize ;размер резидентной
; части
mov es,PspOld ;сегмент старого PSP
int 21h ;выполним
jnc Go2 ;успешно
jmp ErrorRet ;неуспешно
Go2:
;
; подсчитаем сегмент памяти для нового PSP
;
mov ax,ResSize ;длина резидентной
; части в параграфах
add ax,PspOld ; плюс сегмент
; старого PSP
add ax,MCBLen/16 ; плюс длина MCB
mov PspNew,ax ;запомним сегмент
; для нового PSP
;
; создадим новый PSP
;
mov es,PspOld ;адрес старого PSP
mov si,word ptr es:[02h] ; конец памяти
mov ah,55h ;построим
; подчиненный PSP
mov dx,PspNew ;сегмент нового PSP
int 21h ;выполним
;
; скорректируем указатель на родительский PSP в новом PSP
;
mov es,PspOld ;сегмент старого PSP
mov ax,word ptr es:[16h] ;адрес родительского
; PSP
mov es,PspNew ;сегмент нового PSP
mov word ptr es:[16h],ax ;скорректируем
;
; сообщим DOS о новом активном PSP
;
mov bx,PspNew ;сегмент нового PSP
mov ah,50h ;функция указания нового PSP
int 21h ; выполним
;
; укажем принадлежность полученной памяти для нового PSP
;
mov ax,bx ;сегмент нового PSP
sub ax,1 ;сегмент
; построенного MCB
mov es,ax
;==================
mov word ptr es:[01h],bx ;скорректируем адрес
; владельца памяти
;
; переместим резидентную часть на старый PSP
;
mov es,PspOld ;адрес старого PSP
mov cx,ResLen ;размер резидентной
; части
mov di,0 ;куда
mov si,Offset SavRes ;откуда
rep movsb ;переместим
push cs ;восстановим
pop es ; ES
;
; Успешный выход из программы
;
PrgEnd:
mov ah,09h ; выведем сообщение
mov dx,offset MsgInst ; об успешной
; установке
int 21h ;
mov ax,4c00h ;завершим программу
int 21h ; обычным
; образом с кодом 0
;
; Выход из программы по ошибке
;
ErrorRet:
push cs ;установим адресацию
pop ds ; данных
mov ah,09h ; выведем сообщение
mov dx,offset MsgNoInst ; о неуспешной
; установке
int 21h ;
mov ax,4c04h ;завершим программу
int 21h ; обычным
; образом с кодом 4
ini endp
;
code ends
;
; СТЕК
;
stack segment stack
dw 512 dup(0)
stack ends
end ini

Функции прерывания DOS INT 21H

Ниже приведены базовые функции для прерывания DOS INT 21H. Код функции устанавливается в регистре AH:

Завершение программы (аналогично INT 20H).

Ввод символа с клавиатуры с эхом на экран.

Вывод символа на экран.

Ввод символа из асинхронного коммуникационного канала.

Вывод символа на асинхронный коммуникационный канал.

Вывод символа на печать (гл.19).

Прямой ввод с клавиатуры и вывод на экран.

Ввод с клавиатуры без эха и без проверки Ctrl/Break.

Ввод с клавиатуры без эха с проверкой Ctrl/Break.

Вывод строки символов на экран.

Ввод с клавиатуры с буферизацией.

Проверка наличия ввода с клавиатуры.

Очистка буфера ввода с клавиатуры и запрос на ввод.

Установка текущего дисковода.

Открытие файла через FCB.

Закрытие файла через FCB.

Начальный поиск файла по шаблону.

Поиск следующего файла по шаблону.

Удаление файла с диска.

Последовательное чтение файла.

Последовательная запись файла.

Внутренняя операция DOS.

Определение текущего дисковода.

Установка области передачи данных (DTA).

Получение таблицы FAT для текущего дисковода.

Получение FAT для любого дисковода.

Чтение с диска с прямым доступом.

Запись на диск с прямым доступом.

Определение размера файла.

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


Установка вектора прерывания.

Создание программного сегмента.

Чтение блока записей с прямым доступом.

Запись блока с прямым доступом.

Преобразование имени файла во внутренние параметры.

Получение даты (CX-год,DН-месяц,DL-день).

Получение времени (CH-час,CL-мин,DН-с,DL-1/100с).

Установка/отмена верификации записи на диск.

Получение адреса DTA в регистровой паре ES:BX.

Получение номера версии DOS в регистре АХ.

Завершение программы, после которого она остается резидентной в памяти.

Получение вектора прерывания (адреса подпрограммы).

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

Получение государственно зависимых форматов.

Создание подкаталога (команда MKDIR).

Удаление подкаталога (команда RMDIR).

Установка текущего каталога (команда CHDIR).

Создание файла без использования FCB.

Открытие файла без использования FCB.

Закрытие файла без использования FCB.

Чтение из файла или ввод с устройства.

Запись в файл или вывод на устройство.

Удаление файла из каталога.

Установка позиции для последовательного доступа.

Изменение атрибутов файла.

Управление вводом-выводом для различных устройств.

Дублирование файлового номера.

«Склеивание» дублированных файловых номеров.

Получение текущего каталога.

Выделение памяти из свободного пространства.

Освобождений выделенной памяти.

Изменение длины блока выделенной памяти.

Загрузка/выполнение программы (подпроцесса).

Завершение подпроцесса с возвратом управления.

Получение кода завершения подпроцесса.

Начальный поиск файла по шаблону.

Поиск следующего файла по шаблону.

Получение состояния верификации.


Получение/установка даты и времени изменения файла.

Получение расширенного кода ошибки.

Создание временного файла.

Создание нового файла.

Блокирование/разблокирование доступа к файлу.

Получение адреса префикса программного сегмента (PSP).

Порты

Порт представляет собой устройство, которое соединяет процессор с внешним миром. Через порт процессор получает сигналы с устройств ввода и посылает сигналы на устройство вывода. Теоретически процессор может управлять до 65 536 портами, начиная с нулевого порта. Для управления вводом-выводом непосредственно на уровне порта используются команды IN и OUT:

uКоманда IN передает данные из входного порта в регистр AL (байт) или в регистр АХ (слово). Формат команды:

uКоманда OUT передает данные в порт из регистра AL (байт) или из регистра АХ (слово). Формат команды:

Номер порта можно указывать статически или динамически:

1. Статическое указание порта возможно при непосредственном использовании значения от 0 до 255:

Ввод: IN AL.порт# ;Ввод одного байта

Вывод: OUT порт#,АХ ;Вывод одного слова

2. Динамическое указание порта устанавливается в регистре DX от 0 до 65535. Этот метод удобен для последовательной обработки нескольких портов. Значение в регистре DX в этом случае увеличивается в цикле на 1. Пример ввода байта из порта 60Н:

MOV DX,60H ;Порт 60Н (клавиатура)

IN AL,DX ;Ввод байта

Ниже приведен список некоторых портов (номера в шестнадцатеричном представлении):

Регистры маски прерывании.

Ввод с клавиатуры

Звуковой порт (биты 0 и 1)

Монохромный дисплей и параллельный адаптер печати

В случае, если, например, программа запрашивает ввод с клавиатуры, то она выдает команду прерывания INT 16H. В этом случае система устанавливает связь с BIOS, которая с помощью команды IN вводит байт с порта 60Н.

На практике рекомендуется пользоваться прерываниями DOS и BIOS.

Однако можно также успешно обойтись без BIOS при работе с портами 21, 40. 42, 60 и 201.

Конец программы

Доброго вечера, написал решение простенького уравнения на Assembler:

14.10.2020, 19:21

Дописать начало и конец программы
в книге указан пример ;Установим графический режим EGA mov АН,00h ;(1)Функция задания режима.

Конец программы
Здравствуйте! Подскажите, пожалуйста, почему консоль закрывается когда получает все три переменные.

Конец программы посередине
Вот в чем вопрос как закончить программу посередине то есть Закрыть программу или логический.

Не могу додумать конец программы.
Доброго времени суток!) Задание заключается в том, что надо: Программу собственно почти.

Практическая работа Функции ввода и вывода строк прерывания INT 21h
учебно-методический материал на тему

Практическое ознакомление с функциями ввода/вывода строк и приёмами использования возможностей этих функций.

Скачать:

Вложение Размер
pr_rab_int21.doc 386 КБ

Предварительный просмотр:

Функции ввода и вывода строк прерывания INT 21h

1. Цель работы : Практическое ознакомление с функциями ввода/вывода строк и приёмами использования возможностей этих функций .


2. Порядок выполнения работы :

2.1. Повторить теоретический материал .

2.2. Ознакомиться с написанием и сохранение программы в Debug .

Написание и сохранение программы в Debug

Для создания данной программы будем использовать две функции DOS: функцию вывода строки на экран и функцию ввода с клавиатуры.

Функции DOS представляют собой неорганизованную кучу средств управления файлами, устройствами, памятью и процессами, доступных любой программе, которая способна установить регистры и вызвать программное прерывание.

Чтобы обратиться к функции DOS:

— поместить номер функции DOS в регистр AH (если есть подфункции, то номер подфункции обычно помещается в AL)
— загрузить остальные регистры согласно описанию функции
— подготовить необходимые буферы, строки ASCII и управляющие блоки
— вызвать прерывание INT 21H
— проверить индикатор ошибки, возвращенный DOS (флаг переноса)

DOS не изменяет значений регистров, исключая случаи, когда результирующие данные возвращаются через регистры. В процессе развития DOS новые версии остаются (в целом) совместимыми с более ранними версиями.

1). Функция ввода с клавиатуры
вход : AH = 02h
выход : AL = код символа, полученный из стандартного ввода.

Данная функция считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо).

2). Функция вывода строки на дисплей
вход : AH = 09h
DS:DX = адрес строки, заканчивающейся символом ‘$’
выход : нет

Описание :
Строка, исключая завершающий её символ ‘$’, посылается на стандартный вывод.
Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 0Dh и 0Ah).

3). Завершение программы
Вызвать прерывание DOS Int 20h

Подготовка данных (строк) для вывода на экран

Разместим в памяти строки диалога с пользователем для наглядности программы. Для перехода на новую строку будем вводить перед каждой строкой по два байта 0d 0a (см. выше).
Запускаем Debug и записываем в память строки. Запоминаем адреса начала строк, для последующего обращения к ним из программы:

На рис.1 видно, что сначала мы ввели в память два байта 0D и 0A в адреса 13E2:0 200 и 13E2:0 201 соответственно, а далее с адреса 13E2:0 202 расположили первую строку программы «Вариант №4…». Последний байт этой строки символ $, код которого 24h, расположился по адресу 13E2:0 243 . Поэтому продолжаем ввод оставшихся строк с адреса 13E2:0 244 . После введения каждой строки командой «damp»= d просматриваем дамп памяти для определения адреса ввода последующей строки.

mov ax, 900 `подготавливаем функцию вывода строки на экран, AH = 09h
mov dx, 200 `в регистр dx вносим адрес выводимой строки «Вариант №4……»
int 21 `вызываем прерывание DOS для выполнения функции вывода строки на экран
mov dx, 244 `в регистр dx вносим адрес строки «Введите число Х=»
int 21 `вызываем прерывание DOS для выполнения функции вывода строки на экран
mov ax, 100 `подготавливаем функцию ввода символа с клавиатуры, AH = 01h
int 21 `вызываем прерывание DOS для выполнения функции
mov cx, ax `сохраним (скопируем) значение регистра AX (AL = код введённого числа X) в регистре CX для последующего использования (сравнения)
mov ax, 900 `опять готовим функцию вывода на экран, AH = 09h
mov dx, 257 `адрес строки «Введите число Y =»
int 21 `вызываем прерывание DOS для выполнения функции вывода строки на экран
mov ax, 100 `готовим функцию ввода символа, AH = 01h
int 21 `выполняем эту функцию: программа ожидает ввода символа с клавиатуры
mov bx, ax `копируем значение регистра ax (AL = код числа Y) в регистр bx
mov ax, 900 `установим заранее функцию вывода на экран, AH = 09h
cmp cx, bx `сравниваем значения регистров CX и BX, в которые мы сохранили числа X и Y
JG ds:133 `если число Х (т.е.его 16–ричный код) больше числа Y (. ), то переходим к адресу 133, где запрограммирован вывод соответствующей строки на экран
JL ds:13A `если число Х (т.е.его 16–ричный код) меньше числа Y (. ), то переходим к адресу 13A, где запрограммирован вывод соответствующей строки на экран
mov dx, 288 `в dx вносим адрес строки о равенстве чисел X и Y (переходы jg и jl не совершились)
int 21 `прерывание DOS, вывод строки на экран
int 20 `завершение программы
mov dx, 26a `в dx вносим адрес строки «X > Y» (сюда перейдёт по команде jg)
int 21 `прерывание DOS, вывод строки на экран
int 20 `завершение программы
mov dx, 279 `в dx вносим адрес строки «X
int 21 `прерывание DOS, вывод строки на экран
int 20 `завершение программы

Ввод программы в Debug начинаем командой «assembler» – a . Программа записывается с адреса 100 (если нет, то ввести команду a100 ). Сегментный регистр здесь DS = 13E2 (не существенно). В процессе программирования мы его не изменяем, поэтому адресацию производим лишь через регистр DX :

Запись программы на диск

Для записи программы на диск необходимо знать её размер в байтах, и это значение необходимо внести в регистр CX . Последний байт внесённый до этого нами в область данных имеет адрес 296 (см. выше). Это значение и будет размером программы. Вводим это число в регистр CX :

Далее необходимо командой «name»– n ввести имя программы (придумать) и командой «write»– w произвести запись программы в файл :

Для запуска программы вводим команду g :

2.3 Создать и записать программу в отладчике debug для сравнения чисел заданных в варианте (таблица 1).
В качестве имени файла использовать 7 символов своей фамилии.
Для выполнения данной работы необходимо:

1. Запустить Debug.
2. Войти в режим ассемблирования, набрав а после приглашения
3. Запустить программу на выполнение G=100
4 .Сохранить программу, используя команды N, R,W
5. Уметь загрузить программу.
6. Продемонстрировать работу преподавателю в соответствии с вариантом.

2.3. Подготовить отчет (в отчете привести листинг своей программы).

2.4 Отправьте созданный файл преподавателю: Родионову В. И. (vlr@prep.scc).

В теме письма укажите предмет, номер и название практической работы, а также свою фамилию и сетевое имя .

Функции dos int 20h: завершить программу

Что касается машинной программы, записанной загрузчиком в ОП, то кроме собственно машинных команд программы и обрабатываемых ею данных она содержит вспомогательную информацию, называемую префиксом программного сегмента (PSP). Длина PSP 256 (100h) байтов и эта структура данных находится в начале любой машинной программы, вне зависимости от того, получена ли программа загрузкой com— или exe-файла. При этом ни com-, ни exe-файл PSP не содержит. Информация в PSP записывается загрузчиком и используется ОС при выполнении запросов со стороны программы, а также может быть использована самой программой. Структура PSP на рис.58.

Рис. 58. Структура PSP

Для наглядного знакомства со структурой PSP удобно использовать отладчик Debug. Допустим, что мы ранее получили загрузочный модуль программы с именем Prob.com. Тогда для анализа PSP вызовем Debug командой DOS: “Debug Prob.com parametr”, где вместо слова parametr может быть записана любая символьная строка (в коде ASCII), содержащая входные параметры нашей прикладной программы. Эти параметры совершенно не интересуют ни Debug, ни тем более DOS, а используются лишь для передачи в программу какой-то исходной информации. (Кстати, если рассматривать в качестве программы сам Debug, то в качестве его параметра выступает имя исследуемой программы, то есть Prob.com.)

После того как мы запустили Debug описанным выше способом, с помощью команды Debug – “d 0 , получим на экране дамп начальной части PSP. В результате на экран будут выведены первые 128 байтов PSP. Для вывода на экран каждых следующих 128 байтов достаточно просто ввести команду d.

В первых двух байтах PSP находится код машинной команды “int 20h”. (Чтобы убедиться в этом, введем команду Debug – “u ”). Команда программного прерывания выполняет возврат в ОС при завершении программы. Сама же эта команда получает управление следующим образом.

Во-первых, сразу после загрузки программы в память загрузчик помещает в ее стек 16-битное нулевое слово (0000h). Во-вторых, если в конце главной подпрограммы прикладной программы стоит команда ret, то при попадании этой команды на ЦП, в качестве адреса возврата из стека будет выбран 0 и, следовательно, следующей исполняемой командой будет “int 20h”. Следует отметить, что это не единственный способ возвращения из программы в ОС. Например, вместо ret в главной подпрограмме можно записать оператор “int 20h”. В этом случае управление из программы возвращается в ОС непосредственно, минуя PSP. Другой способ возврата – запись в конце главной подпрограммы команды “int 21h” (функция 4Ch). Этот способ является наиболее предпочтительным, так как он позволяет возвращать из программы в ОС код возврата (в регистре AL), информирующий операционную систему о причине завершения программы.

В следующих двух байтах PSP находится верхняя граница (адрес-сегмент) ОП. Обычно она равна величине A000h. В дальнейшем мы еще вернемся к этой величине, когда будем рассматривать распределение ОП.

В пяти байтах PSP, начиная с 05h, находится вызов диспетчера функций DOS. Данный вызов представляет собой команду дальнего вызова процедуры. С помощью команды Debug – “u 5 ” мы можем получить на экране, например следующее: “call F01D:FEF0”, где F01D – адрес-сегмент, а FEF0 – адрес-смещение первой команды диспетчера функций DOS. (Соответствующий реальный адрес интересен тем, что он находится за пределами первого мегабайта. Мы вернемся к нему в вопросе о распределении памяти.)

Для того чтобы обратиться из программы к DOS (с целью получения помощи), достаточно поместить в нее команду “call 5 ” . В результате следующей командой, исполняемой на ЦП, будет команда вызова диспетчера функций. (Данный способ обращения к DOS менее предпочтителен по сравнению с командой программного прерывания “int 21h”.)

В двенадцати байтах PSP, начиная с 0Ah, содержатся копии векторов прерываний с номерами 22h, 23h, 24h. Эти прерывания DOS использует для управления выполнением программы. При этом прерывание 22h используется для вызова той подпрограммы, которая должна получить управление при завершении прикладной программы. Прерывание 23h происходит при нажатии клавиш + . (DOS использует для обработки этой комбинации специальный обработчик.) Причинами прерывания 24h являются аппаратные ошибки при работе с ПУ. Некоторые из этих ошибок: 1) попытка записи на защищенный диск; 2) нет бумаги на принтере; 3) неизвестное устройство. Хранение копий векторов перечисленных прерываний обусловлено тем, что в случае, если прикладная программа изменяет содержимое векторов (с целью выполнить свою обработку прерываний), то после ее завершения DOS восстанавливает прежнее содержимое векторов, используя копии из PSP.

По адресу 16h находится адрес-сегмент PSP родительской программы. Назначение этого поля будет понятно позже. Следующее поле PSP начинается по адресу 18h и имеет длину 20 байтов. В нем размещена таблица логических номеров файлов, которая будет рассмотрена в другом разделе.


Начиная с ячейки 2Ch, два байта PSP содержат адрес-сегмент блока окружения программы. Блок окружения – совокупность переменных окружения. Переменная окружения – символьная строка в коде ASCII, имеющая структуру:

После последней переменной окружения записывается не один, а два нулевых байта (0000h). Пример переменной окружения:

PATH = C:\WINDOWS; C:\WINDOWS\COMMAND00h

Данная переменная задает те каталоги (директории), в которых могут находиться используемые программой файлы. В том случае, если на вход программы поступает не имя-путь файла, а лишь завершающая часть этого имени, то для получения имени-пути программа должна последовательно просмотреть заданные значения переменной окружения PATH. В случае обнаружения в очередном каталоге искомого файла имя-путь каталога соединяется с именем файла в единое имя-путь файла.

Допустим, что с помощью команды Debug – “d 0 ” мы прочитали значение адреса-сегмента блока окружения, равное 2065. Тогда для получения на экране содержимого блока окружения следует воспользоваться командой “d 2065:0”. Первоначальное содержимое своего блока окружения программа получает «в наследство» от той программы, которая создает данную программу, используя системный вызов EXEC (int 21h, функция 4Bh). Данный вызов будет рассматриваться позже. А сейчас лишь заметим, что программа может не только читать свои переменные окружения, но и вносить в них изменения.

По адресу 5Ch находятся два блока управления файлами, используемые при работе с линейными файловыми структурами. Так как эти структуры сейчас полностью вытеснены иерархическими файловыми структурами, соответствующее поле PSP может использоваться для хранения любой другой информации. Например, учитывая, что подобно блоку окружения данные блоки управления передаются «по наследству», родительская программа может помещать в них исходные данные для дочерней программы. Другой способ передачи исходных данных в программу заключается в использовании «хвоста» команды.

Хвост команды – остаток команды ОС (после имени программы), запустившей прикладную программу. Иными словами, хвост содержит параметры команды, а также пробелы, которые были набраны в командной строке. В приведенном выше примере хвостом является слово parametr, предваряемое одним пробелом. Для размещения хвоста используется поле в PSP, начиная с ячейки 81h. Длина хвоста содержится в байте 80h. (Убедитесь в этом, используя Debug.)

Пример. Следующая простая com-программа выводит на экран свои параметры (хвост команды).

; Программа выводит на экран свои параметры

absolute 80h ; Следующий байт имеет адрес-смещение 80h

Lparam resb 1 ; Длина хвоста команды

Param resb 1 ; Первый байт хвоста

segment code ; Виртуальный сегмент кода

Основные функции прерывания MS DOS 21h

Прерывание 21h (DOS) предназначено для предоставления программисту различных услуг со стороны DOS. Этими услугами является набор функций.

Последовательность действий при использовании этих функций:

1. Поместить номер функции в регистр AH. Если используется функция с подфункцией, то номер подфункции обычно помещается в регистр AL.

2. Поместить передаваемые функции параметры в определенные регистры (для каждой ф-ции соответствующие)

3. Вызвать прерывание командой int 21h

4. Извлечь рез-ты работы функции из определенных регистров

Основные функции ввода, вывода для прерывания 21h:

00h — завершение работы программы

01h – ожидание набора символа с последующим его эхосопровождением и с проверкой на CTRL+BREAK

На выходе в AL — ACSII-код символа.

02h – изображение (вывод) символа с проверкой на CTRL+BREAK.

На входе в DL — ACSII-код символа

05h — вывод символа на принтер.

На входе в DL — ACSII-код символа

06h – изображение символа без проверки на CTRL+BREAK.

На входе в DL — ACSII-код символа

07h – ожидание набора символа без последующего его эхосопровождения и без проверки на CTRL+BREAK

На выходе в AL — ACSII-код символа.

08h – ожидание набора символа с последующим его эхосопровождением и с проверкой на CTRL+BREAK

На выходе в AL — ACSII-код символа.

09h — изображение строки символов с проверкой на CTRL+BREAK.

На входе — DS:DX = начальному адресу строки с символом $ на конце.

0ah – чтение строки в буфер клавиатуры.

На входе DS:DX = адрес буфера с форматом:


1 байт — размер буфера для ввода (формирует пользователь)

2 байт — число фактически введенных символов (заполняет система по окончанию ввода-нажатию Enter (0dh), этот символ не считает)

3 байт и далее — введенная строка с символом 0dh на конце

На выходе — введенная строка в буфере

0bh – чтение состояния клавиатуры

На выходе AL = 0 — буфер НЕ пуст

AL = offh – буфер клавиатуры пуст

0сh – освобождение буфера клавиатуры и вызов нужной функции

На входе в AL – номер нужной функции

На выходе – регистры в соответствии с вызываемой функцией

Проверка на CTRL+BREAK означает, что если в процессе работы данной функции была нажата эта комбинация клавиш, то по умолчанию происходит прерывание 23h и выход из программы.

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Увлечёшься девушкой-вырастут хвосты, займёшься учебой-вырастут рога 9792 — | 7667 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Разработка виртуальных лабораторных работ средствами эмулятора Emu8086 (стр. 7 из 21)

Возврат из подпрограммы возвращаемся в то место, откуда вызывали

В данном примере мы дважды вызвали подпрограмму Сложение, которая сложила два числа, переданные ей в переменных A и B. Результат помещается в переменную С. Когда вызывается подпрограмма, компьютер запоминает с какого места она была вызвана, а затем, когда закончила работу подпрограмма, компьютер возвращается в то место, откуда она вызывалась. Т.о. можно вызывать подпрограммы неопределенное количество раз с любого места.

Команда RET пользуется обычно для возвращения из процедуры. DOS вызывается COM-программы так, что команда RET корректно завершает программу.

DOS при вызове СОМ-файла помещает в стек сегментный адрес программы и ноль, так что RET передает управление на нулевой адрес текущего сегмента, то есть на первый байт PSP. Там находится код команды INT 20H, которая и используется для возвращения управления в DOS. Можно сразу заканчивать программу командой INT 20h, хотя это длиннее на 1 байт.

Следующая строка примера определяет строку данных, содержащую текст “ПРИВЕТ» управляющий символ ASCII возврат каретки с кодом ODh, управляющий символ ASCII перевод строки с кодом 0Ah и символ $ завершающий строку (если мы его уберем, то 21h прерывание продолжит вывод до тех пор, пока не встретится где-нибудь в памяти символ $, на экране мы увидим “мусор). Первое слово (message — сообщение) — название сообщения. Оно может быть любым (например, mess или string и пр).

Управляющие символы (ODh и 0Ah) переводят курсор на первую позицию следующей строки.

Директива END завершает программу, одновременно указывая, с какой метки должно начинаться ее выполнение.

В качестве дополнительного примера создадим еще одну строку, которую назовем message1. Затем, начиная со строки (9) вставим следующие команды и скомпилируем программу заново.

9 mov dx,offset message1
10 int 21h
11 int 20h
12 message db «Привет», 0dh, 0ah, ‘$’
13 message1 db «Группа», 0dh, 0ah, ‘$’
14 end begin

2. Задание для выполнения

2.1 Запустить эмулятор EMU8086.

2.2 Пользуясь правилами оформления ассемблерных программ, наберите код, приведенный в примере 1, запустите код на выполнение.

2.3 Откомпилируйте пример №2;

2.4 Вернитесь в главное окно формы, предварительно закрыв все открытые окна, далее нажмите кнопку “Compile».

2.5 Полученный com-файл запустите в сеансе dos.

2.6 Создайте на языка Pascal программу выводящую на экран слово “Привет» и сравните размеры получаемых файлов (Pascal и Assembler).

3. Контрольные вопросы

3.1 Характеристика структуры файла типа *.com?

3.2 Какова структура ассемблерной программы?

3.3 С какой целью в код программы на ассемблере для DOS вводится строка ORG 100h?

3.4 Назначение команды MOV?

3.5 Прерывания 21h и 20h. Назначение?

3.6 Сущность и целесообразность использования команды RET вместо прерывания 20h?


3.6. Символ ‘$’ методика применения?

3.7. Связка “BEGIN: — END BEGIN». Правила применения?

ЛАБОРАТОРНАЯ РАБОТА №3

СТРУКТУРА ИСПОЛНИМЫХ ФАЙЛОВ ТИПА *. EXE.

ПРОСТЫЕ АРИФМЕТИЧЕСКИЕ ДЕЙСТВИЯ НА ЯЗЫКЕ АССЕМБЛЕРА

Цель работы: Изучение принципов составления простейших*. exe программ. Изучение приемов работы с простейшими операторами арифметических действий.

Краткие теоретические сведения (программа типа *. ЕХЕ).

Файлы типа ЕХЕ содержат заголовок, в котором описывается размер файла, требуемый объем памяти, список команд в программе, использующих абсолютные адреса, которые зависят от расположения программы в памяти, и т.д. ЕХЕ-файл может иметь любой размер. Формат ЕХЕ также используется для исполнимых файлов в различных версиях DOS-расширителей и Windows, но со значительными изменениями.

Операционная система DOS не использует расширения для определения типа файла. Первые два байта заголовка ЕХЕ-файла — символы «MZ» или «ZM», и если файл начинается с этих символов и длиннее некоторого порогового значения, разного для разных версий DOS, он загружается как ЕХЕ, если нет — как СОМ.

ЕХЕ-программы немного сложнее в исполнении, но для них отсутствует ограничение размера в 64 килобайта, так что все достаточно большие программы используют именно этот формат. Конечно, ассемблер позволяет уместить и в 64 килобайтах весьма сложные и большие алгоритмы, а все данные хранить в отдельных файлах, но ограничение размера все равно очень серьезно, и даже чисто ассемблерные программы могут с ним сталкиваться.

Простой пример ЕХЕ-файла :

. model small ; сегмент стека размером в 256 байт
. stack 100h ; сегмент стека размером в 256 байт
. code ; сегмент кода, который содержит и данные.
Begin: ; метка начала кода программы
mov ax,@data; ; сегментный адрес строки message помещается в DS
mov ds,ax
mov dx,offset string помещает в регистр DX смещение метки String относительно начала сегмента данных
mov ah,9 ; помещаем номер функции DOS «вывод строки (9)» в регистр АН.
int 21h ; функция DOS «вывод строки»
mov ax,4C00h ; завершение программы типа — exe
int 21h ; функция DOS «завершить программу»
. data ; начало сегмента данных
string db «Privet», 0Dh,0Ah,’$’ ; cтрока с содержащая выводимые данные.
end begin ; метка окончания кода программы

В примере определяются три сегмента — сегмент стека директивой. STACK размером в 256 байт, сегмент кода, начинающийся с директивы. CODE, и сегмент данных, начинающийся с. DATA. При запуске ЕХE-программы регистр DS уже не содержит адреса сегмента со строкой string (он указывает на сегмент, содержащий блок данных PSP), а для вызова используемой функции DOS этот регистр должен иметь сегментный адрес строки. Команда MOV AX,@DATA загружает в АХ сегментный адрес группы сегментов данных @DATA, a MOV DS,AX копирует его в DS. Программы типа ЕХЕ должны завершаться системным вызовом DOS 4Ch: в регистр АН помещается значение 4Ch, в регистр AL помещается код возврата (в данном примере код возврата 0 и регистры АН и AL загружаются одной командой MOV AX,4C00h), после чего вызывается прерывание 21h.

Простые арифметические операторы.

Арифметические команды любого микропроцессора привлекают к себе наибольшее внимание. Каждый заинтересован в выполнении арифметических вычислений, и именно эти команды проделывают такую работу. Хотя их немного, они выполняют большинство преобразований данных, а микропроцессоре. В реальных же условиях арифметические команды занимают лишь малую часть всех исполняемых команд.

Команда ADD (Addition — сложение (гл. to add — сложить)) осуществляет сложение первого и второго операндов. Исходное значение первого операнда (приемника) теряется, замещаясь результатом сложения. Второй операнд не изменяется. В качестве первого операнда команды ADD можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команду ADD можно использовать для сложения как обычных целых чисел, так и двоично-десятичных (с использованием регистра АХ для хранения результата). Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.

Команда Назначение Процессор
ADD приемник, источник Сложение 8086

mov al,10 — загружаем в регистр AL число 10

add al,15 — al = 25; al — приемник, 15 — источник

mov ax,25000 — загружаем в регистр AX число 25000

add ax,10000 — ax = 35000; ax — приемник, 10000 — источник

mov cx, 200 — загружаем в регистр CX число 200

mov bx,760 — а в регистр BX — 760

add cx,bx — cx = 960, bx = 760 (bx не меняется); cx — приемник, bx — источник

Команда SUB (Subtraction — вычитание) вычитает второй операнд (источник) из первого (приемника) и помещает результат на место первого операнда. Исходное значение первого операнда (уменьшаемое) теряется. Таким образом, если команду вычитания записать в общем виде

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

то ее действие можно условно изобразить следующим образом:

операнд1 — операнд2 — > операнд1

В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.

Команда Назначение Процессор
SUB приемник, источник Вычитание 8086

sub al,7 — al = 3; al — приемник, 7 — источник

sub ax,10000 — ax = 15000; ax — приемник, 10000 — источник

sub cx,bx — cx = 85, bx = 15 (bx не меняется); cx — приемник, bx — источник

2.3 Инкремент (увеличение на 1).

Команда INC (Increment — инкремент) прибавляет 1 к операнду, в качестве которого можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово.

Не допускается использовать в качестве операнда непосредственное значение. Операнд интерпретируется как число без знака. Команда воздействует на флаги OF, SF, ZF, AF и PF. Команда не воздействует на флаг CF; если требуется воздействие на этот флаг, необходимо использовать команду Add Op,l.

Команда INC (Increment — инкремент) увеличивает на единицу регистр или значение операнда в памяти.

Она эквивалентна команде ADD источник, 1 только выполняется гораздо быстрее.

Функция DOS 02h


1.1 Функция DOS 02h.

Функция DOS 02h — Записать символ в STDOUT с проверкой на Ctrl-Break

DL = ASCII-код символа

Вывод: Никакого, согласно документации, но на самом деле: AL = код последнего записанного символа (равен DL, кроме случая, когда DL = 09h (табуляция), тогда в AL возвращается 20h).

Эта функция при выводе на экран обрабатывает некоторые управляющие символы — вывод символа BEL (07h) приводит к звуковому сигналу, символ BS (08h) приводит к движению курсора влево на одну позицию, символ НТ (09h) заменяется на несколько пробелов, символ LF (0Ah) опускает курсор на одну позицию вниз, и CR (0Dh) приводит к переходу на начало текущей строки.

Если в ходе работы этой функции была нажата комбинация клавиш Ctrl-Break, вызывается прерывание 23h, которое по умолчанию осуществляет выход из программы.

Простой пример работы функции DOS 02h.

. model tiny ; модель памяти в которой сегменты кода, данных и стека объединены.
. code ; сегмент кода, который содержит данные.
org 100h ; начало СОМ-файла
begin: ; метка начала кода программы
mov dl, ; заносим в регистр dl — любой ASCII-код символа
mov ah,2 ; номер функции DOS «вывод символа»
int 21h ; вызов DOS
ret ; функция DOS «завершить программу»
end begin ; метка окончания кода программы

Эта программа, выводит на экран любой ASCII-символ, в установленную позицию курсора.

Все функции DOS вывода на экран используют устройство STDOUT, стандартный вывод. Это позволяет перенаправлять вывод программы в файл или на стандартный ввод другой программы. Например, если откомпилировать приведен пример (создать файл cod.com) и написать в командной строке

cod.com > cod. out

то на экран ничего выдано не будет, а в текущем каталоге появится файл cod. out, содержащий ASCII-код символа.

Функция DOS 06h.

Функция DOS 06h — Записать символ в STDOUT без проверки на Ctrl-Break

DL = ASCII-код символа (кроме FFh)

Вывод: Никакого, согласно документации, но на самом деле: AL = код записанного символа (копия DL)

Эта функция не обрабатывает управляющие символы (CR, LF, HT и BS выполняют свои функции при выводе на экран, но сохраняются при перенаправлении вывода в файл) и не проверяет нажатие Ctrl-Break.

Заменим в примере № 1.1 MOV АН,2 на MOV АН,6 и перекомпилируем этот пример. Работу откомпилированного примера смотрим в операционной системе MS-DOS.

Функция DOS 09h

Функция DOS 09h — Записать строку в STDOUT с проверкой на Ctrl-Break

Ввод: АН = 09h DS: DX = адрес строки, заканчивающейся символом $ (24h)
Вывод: Никакого, согласно документации, но на самом деле: AL = 24h (код последнего символа)

Действие этой функции полностью аналогично действию функции 02h, но выводится не один символ, а целая строка (смотри лабораторную работу №2).

1.4 Функция DOS 40h

Функция DOS 40h — Записать в файл или устройство

Ввод: АН = 40h ВХ = 1 для STDOUT или 2 для STDERR DS: DX = адрес начала строки СХ = длина строки
Вывод: CF = 0, АХ = число записанных байт

Эта функция предназначена для записи в файл, но, если в регистр ВХ поместить число 1, функция 40h будет выводить данные на STDOUT, а если ВХ = 2 — на устройство STDERR. STDERR всегда выводит данные на экран и не перенаправляется в файлы. На этой функции основаны используемые в С функции стандартного вывода — фактически функция С fputs () просто вызывает это прерывание, помещая свой первый аргумент в ВХ, адрес строки (второй аргумент) — в DS: DX и длину — в СХ.

Простой пример работы функции DOS 40h.

. model tiny ; модель памяти в которой сегменты кода, данных и стека объединены.
. code ; сегмент кода, который содержит данные.
org 100h ; начало СОМ-файла
begin: ; метка начала кода программы
mov ah,40h ; номер функции DOS
mov bx,2 ; указываем устройство STDERR
mov dx,offset message ; DS: DX — адрес строки
mov cx,25 ; CX — длина строки
int 21h ; вызов DOS
ret ; функция DOS «завершить программу»
message db «This function can print $» ; cтрока с содержащая выводимые данные.
end begin ; метка окончания кода программы

Если скомпилировать этот пример и запустить ее командой

dosout.com > dosout. out

то сообщение появится на экране, а файл dosout2. out окажется пустым.

Прерывание INT 29H

INT 29h: Быстрый вывод символа на экран

Ввод: AL = ASCII-код символа

Простой пример работы прерывания INT 29h.

. model tiny ; модель памяти в которой сегменты кода, данных и стека объединены.
. code ; сегмент кода, который содержит данные.
org 100h ; начало СОМ-файла
begin: ; метка начала кода программы
mov ax, ; заносим в регистр ax — любой ASCII-код символа
int 29h ; вызов прерывания DOS — вызов символа;
ret ; функция DOS «завершить программу»
end begin ; метка окончания кода программы

В большинстве случаев INT 29h просто немедленно вызывает функцию BIOS «вывод символа на экран в режиме телетайпа», так что никаких преимуществ, кроме экономии байт при написании как можно более коротких программ, она не имеет.

2. Средства BIOS

Функции DOS вывода на экран позволяют перенаправить вывод в файл, но не позволяют вывести текст в любую позицию экрана и не позволяют изменить цвет текста. DOS предполагает, что для более тонкой работы с экраном программы должны использоваться видеофункции BIOS. BIOS — обеспечивает доступ к некоторым устройствам, в частности к видеоадаптеру. Все функции видеосервиса BIOS вызываются через прерывание 10h.

Илон Маск рекомендует:  Что такое код xml_set_unparsed_entity_decl_handler
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL