
157A:0100 int 20
157A:0102
-g
Program terminated normally
Функции операционной системы вызываются с помощью команды int 21h. Номер функции передается в регистре AH. В другие регистры программист помещает входные параметры системной функции.
Примеры. 1. Вместо устаревшего системного вызова int 20h фирма Microsoft настоятельно рекомендует применять функцию 4Сh. Описание этой функции имеет вид:
Вход: AH = 4Ch — номер функции;
AL — код возврата.
Код возврата можно использовать, например, в командных файлах, чтобы в зависимости от его величины осуществлять запуск на выполнение той или иной программы. Принято, что если программа выполнилась нормально, то ее код возврата равен нулю.
2. Функция вывода строки на экран.
Вход: AH = 09h — номер функции;
DS:DX — адрес строки. Строка заканчивается символом $, т.е. символ '$' (код ASCII24h) является терминатором (завершителем) строки.
Испытаем эту функцию в debug:
-e120 'Example$' (Заносим в память строку по адресу DS:0120)
-a
157A:0100 mov ah,9 ; (номер функции — в AH)
157A:0102 mov dx,120 ; (адрес строки — в DX)
157A:0105 int 21h ; (вызов функции вывода строки на экран)
157A:0107 int 20 ; (завершение работы программы)
157A:0109
-g
Example
Program terminated normally
3. Вывод на экран одиночного символа.
Вход: AH = 02h — номер функции;
DL — код символа.
Задача. Наберите в debugпрограмму, выводящую фразу: "Товар стоит $1000." (Сделайте два решения: 1) только циклический вызов функции 02h; 2) один раз вызвать функцию 09hи дважды функцию 02h(код точки — 2Eh)).
Решение.
-e180 "Товар стоит 1000$."
-a100
1678:0100 mov cx,12 ; В строке 18 = 12hсимволов
1678:0103 mov si,180 ; Адрес (смещение) строки вSI
1678:0106 mov ah,02 ; Функция вывода символа
1678:0108 mov dl,[si] ; Поместить очередной символ строки вDL
1678:010A inc si ; Переместить указатель на следующий элемент
1678:010B int 21 ; Вывод строки
1678:010D loop 108
1678:010F nop
1678:0110
-g=100 10f
2)
-e200 "Товар стоит 1000$"
-a100
1678:0100 mov dx,200
1678:0103 mov ah,9
1678:0105 int 21
1678:0107 mov ah,2
1678:0109 mov dl,24
1678:010B int 21
1678:010D mov dl,2E
1678:010F int 21
1678:0111 nop
1678:0112
9.6. Написание обработчика прерываний
Напишем программу обработки прерываний для команды into, которая эквивалентна командеint4.
Упражнение. Убедитесь, что текущий обработчик прерываний дляintoсостоит из одной команды (какой?).
Тестовую программу и обработчик создадим в debug.
D:\>debug
Тестовая программа
-a100
157D:0100 mov al,7f
157D:0102 mov bl,7f
157D:0104 add al,bl
157D:0106 into
157D:0107 nop
157D:0108
Обработчик прерывания будет выводить сообщение "Overflow!"
-a200
157D:0200 sti
157D:0201 mov dx,300
157D:0204 mov ah,9
157D:0206 int 21
157D:0208 iret
157D:0209
-a300
157D:0300 db 'Overflow!$'
157D:030A
Заполним вектор прерывания смещением и сегментным адресом обработчика
-a0:10
0000:0010 dw 0200,157d
0000:0014
Приступим к трассировке. Покажем только часть выводимой информации.
-r
… SP=FFEE …
157D:0100 B07F MOV AL,7F
-t
…
157D:0102 B37F MOV BL,7F
-t
…
157D:0104 00D8 ADD AL,BL
-t
…
… OV … EI … (знаковое переполнение, внешние прерывания разрешены)
157D:0106 CE INTO
-t
… DI … (внешние прерывания запрещены)
157D:0200 FB STI
-t
… EI … (внешние прерывания разрешены)
157D:0201 BA0003 MOV DX,0300
-t
…
157D:0204 B409 MOV AH,09
-t
…
157D:0206 CD21 INT 21
-p (ни в коем случае не t, иначе мы войдем в диспетчер int 21h)
Overflow!
… SP=FFE8 …
157D:0208 CF IRET
Посмотрим содержимое стека.
-dffe8L8
157D:FFE0 07 01 7D 15 92 7A 00 00 ..}..z..
Это означает, что содержимое стека следующее:
FFEE |
0 |
|
FFEC |
7A92 |
Flags |
FFEA |
157D |
CS |
FFE8 |
0107 |
IP |
-t
… SP=FFEE …
… IP=0107 …
157D:0107 90 NOP
Изменим тестовую программу.
-a100
157D:0100 mov al,0
157D:0102
-t=100
…
157D:0102 B37F MOV BL,7F
-t
…
157D:0104 00D8 ADD AL,BL
-t
…
…NV… (знакового переполнения нет)
157D:0106 CE INTO
-t
157D:0107 90 NOP
(обработчик прерывания не был вызван)
-q
Упражнение. Выполните эти же действия вTurboDedugger.
Заметим, что такое грубое вторжение в область векторов прерываний, которое мы осуществили в этом примере, не рекомендуется. Для изменения вектора прерывания нужно использовать специальную функцию DOS. Нам еще предстоит с ней познакомиться.