Знакомство с прерываниями
Выход из программы
Ввод программы
Команда MOV
Запись программы на диск
Вывод на экран строки символов
Редактирование строк
Как уже отмечалось ранее, микропроцессор оперирует двоичными числами. Но на экране компьютера мы видим привычные символы: цифры, буквы и знаки. Данная тема раскроет секреты вывода на экран отдельных символов и строк.
Знакомство с прерываниями
Множество полезных операции на ассемблере выполняется с помощью инструкции INT (Interrupt - прерывание). Печать символов и строк выполняется прерыванием "INT 21h". Например, требуется вывести на экран символ "A":
- В регистр AH занесите функцию 02h (вывод символа): AX = 0200h
- В регистр DL занесите ASCII код символа "A": DX = 0041h
- Коды [CDh, 21h] инструкции INT 21h занесите в память по адресам: 100h и 101h
- Установите регистр IP = 100h
- Просмотрите регистры и убедитесь, что инструкция записана верно: "INT 21h"
Прерывание INT 21h выполняет функцию, заданную в регистре AH. Подпрограмма функции содержит значительное количество инструкций, поэтому трассировка прерывания может завести нас очень далеко. Для выполнения прерывания используем команду "G" (Go), которая выполняет все инструкции подряд. Адрес остановки (т.е. адрес инструкции, следующей за INT 21h) мы укажем непосредственно в команде G:
-g 102
A
AX=0241 BX=0000 CX=0000 DX=0041 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0102 NV UP EI PL NZ NA PO NC
0ABD:0102 96 XCHG SI,AX
Операционная система вывела букву "A" и передала управление Debug. По причинам рассмотренным ранее, последняя строка вашего листинга будет выглядеть иначе.
Используя инструкцию INT 21h, выведите следующие символы на экран:
Z, F, Я, Ю, @, *, #, 9, ^.Таблица ASCII кодов
В качестве эксперимента попробуйте трассировать прерывание. Завершить трассировочный "поход" по инструкциям прерывания можно командой "G 102". Аналогичный эксперимент проделайте с командой G, не указывая в ней точку остановки.
Выход из программы
INT 20h - это прерывание, которое сообщает операционной системе о выходе из программы, и о передаче управления консольному приложению. Значит, при использоании INT 20h в наших примерах, управление будет передаваться программе Debug.
Введите коды [CDh, 20h] по адресам 100h и 101h. Проверьте наличие инструкции INT 20h командой "R", и выполните прерывание командой "G":
-g
Program terminated normally
Прерывание INT 20h сообщает об успешном выполнении программы, и передает управление Debug. Кроме того, INT 20h восстанавливает содержимое всех регистров к виду, в котором они были до запуска программы. То есть, после выполнения INT 20h регистр IP вернется в исходное состояние: IP = 100h.
Инструкцию INT 20h логично добавлять в конец каждой программы. Например, объединим INT 21h и INT 20h в одну программу, которая будет печатать заданный символ на экран:
- По адресам 100h и 101h введите коды инструкции INT 21h [CDh, 21h].
- По адресам 102h и 103h введите коды инструкции INT 20h [CDh, 20h].
Ранее, выполняемую инструкцию мы просматривали в листинге регистров. Для просмотра сразу двух инструкций мы используем команду "U" (Unassemble) - дизассемблирование:
-u 100
0ABD:0100 CD21 INT 21
0ABD:0102 CD20 INT 20
0ABD:0104 42 INC DX
0ABD:0105 007538 ADD [DI+38],DH
0ABD:0108 8E062850 MOV ES,[5028]
0ABD:010C 26 ES:
0ABD:010D 8B1E7200 MOV BX,[0072]
0ABD:0111 1E PUSH DS
0ABD:0112 FFB7FE05 PUSH [BX+05FE]
0ABD:0116 8D840B01 LEA AX,[SI+010B]
0ABD:011A 1E PUSH DS
0ABD:011B 50 PUSH AX
0ABD:011C 3400 XOR AL,00
0ABD:011E AC LODSB
0ABD:011F 0A29 OR CH,[BX+DI]
Курсивом помечены инструкции, оставшиеся от программ или данных, отработавших до запуска Debug. С увеличением сложности примеров, размер дизассемблированного листинга также будет увеличиваться.
Занесите в регистр AH функцию 02h, а в регистр DL код символа "#". Запустите программу:
-g
#
Program terminated normally
Проверьте работу программы с другими символами. Таблица ASCII кодов
Ввод программы
До сих пор мы вводили коды инструкций, например: [CDh, 21h]. Но это очень неудобно. В Debug имеется команда "A" (Assemble), позволяющая вводить мнемокоды инструкций:
-a 100
0ABD:0100 INT 21
0ABD:0102 INT 20
0ABD:0104 <Enter>
Параметр 100 означает, что ввод инструкций начнется с адреса 100h.
Команда MOV
Команда "R" позволяет изменять значения регистров до и после запуска программы. В ходе программы, число в регистр можно загрузить командой MOV. Например, загрузим функцию печати числа в регистр AH следующим образом:
-a 100
0ABD:0100 MOV AH,02
0ABD:0102 <Enter>
Проверьте наличие команды в листинге регистров:
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0100 NV UP EI PL NZ NA PO NC
0ABD:0100 B402 MOV AH,02
В исходном состоянии AX = 0000. Выполните трассировку, и вновь просмотрите регистры. Теперь AX = 0200 (AH = 02h).
Команда MOV позволяет копировать числа из регистра в регистр. Например, скопируем число из регистра BX в регистр AX:
-a 100
0ABD:0100 MOV AX,BX
0ABD:0102 <Enter>
Загрузите в регистры числа: AX = FF00, BX = 00EE. Выполните трассировку команды. После просмотра регистров вы увидите, что AX = 00EE. Содержимое регистра BX не изменилось.
Следующая программа демонстрирует возможности команды MOV:
-a 100
0ABD:0100 MOV AX,FEFE
0ABD:0102 MOV BX,AX
0ABD:0104 MOV CX,BX
0ABD:0106 MOV DX,CX
Выполните трассировку, анализируя каждый шаг программы.
Команда MOV имеет два ограничения:
- нельзя загружать в байтовые регистры слово: MOV AH,FE4B
- нельзя передавать числа между регистрами разного типа: MOV DL,BX
Используем команду MOV, для модернизации программы вывода символа на экран:
-a 100
0ABD:0100 MOV AH,02
0ABD:0102 MOV DL,2A
0ABD:0104 INT 21
0ABD:0106 INT 20
Программа будет печатать символ "*" (ASCII код 2Ah). Используйте команду "U 100" для проверки введенных инструкций. Убедитесь, что регистр IP = 100h. Выполните программу:
-g
*
Program terminated normally
Запись программы на диск
В предыдущем разделе была рассмотрена программа вывода на экран символа "*". Чтобы записать эту программу на диск, следует выполнить три действия:
- присвоить программе имя;
- указать длину программы;
- выполнить запись.
Если программа вывода звездочки уже потеряна, то обратитесь к предыдущему разделу для ее повторного ввода.
Используя команду "N" (Name), присвойте будущему файлу имя:
-n star.com
Программа состоит из четырех двухбайтных инструкций, значит ее длина - 8 байт. Размер программы Debug хранит в регистровой паре [BX:CX]. Регистровая пара позволяет хранить числа размером до FFFFFFFFh. В нашем случае значение длины умещается в одном регистре, поэтому старший регистр пары мы просто обнулим: BX = 0, CX = 8.
Для записи программы на диск используйте команду "W" (Write):
-w
Writing 00008 bytes
Если вы используете FAR, то программа будет записана на диск в текущий каталог. Покиньте Debug и запустите программу Star.com. В приложении FAR, результат выполнения Star.com будет скрыт панелями. Включить/выключить панели FAR можно комбинацией: [Ctrl] + [O].
Вывод на экран строки символов
Как отмечалось ранее, прерывание INT 21h может выполнять несколько различных функций. Мы рассмотрели функцию 02h, которая выводит на экран отдельные символы. Для вывода на экран строк, используется функция 09h. Например, требуется вывести на экран строку:
We are the champions!
Список ASCII кодов для этой строки следующий:
57 65 20 61 72 65 20 74 68 65 20 63 68 61 6D 70 69 6F 6E 73 21 24
В конец строки добавляется символ "$" (ASCII код 24h) - это признак конца строки. Получив этот код, прерывание прекращает чтение строки из памяти.
Начиная с адреса 109h, запишите в память коды строки. Переход от одной ячейки памяти к другой выполняйте клавишей [пробел]:
-e 109
0ABD:0109 03.57<пробел> 1F.65<пробел> и т.д.
Проверьте введенные коды командой "D" (Dump - дампирование памяти):
-d 109
0ABD:0100 57 65 20 61 72 65 20 We are
0ABD:0110 74 68 65 20 63 68 61 6D-70 69 6F 6E 73 21 24 0A the champions!$.
0ABD:0120 75 12 80 3E 07 96 00 BA-DD 89 75 03 E9 17 01 C6 u..>......u.....
0ABD:0130 06 13 99 01 B8 00 6C BE-FC 97 BB 21 00 33 C9 BA ......l....!.3..
0ABD:0140 01 01 80 3E 13 99 00 75-03 BA 12 01 CD 21 73 11 ...>...u.....!s.
0ABD:0150 E8 2D DE C7 06 E0 97 FC-97 C6 06 B6 89 01 E9 E5 .-..............
0ABD:0160 00 A3 53 98 C6 06 11 96-01 8B D8 B8 00 44 CD 21 ..S..........D.!
0ABD:0170 88 16 55 98 F6 C2 80 74-33 A0 0D 96 24 0C 75 09 ..U....t3...$.u.
0ABD:0180 A0 18 99 0A 06 14 99 74-19 .......t.
Фактически, дамп - это листинг памяти, в основной области которого печатаются коды, а с правой стороны выводятся соответствующие им символы. Для наглядности, коды введенной строки выделены жирным шрифтом.
Начиная с адреса 100h, введите в память программу:
-a 100
0ABD:0100 B409 MOV AH,09
0ABD:0102 BA0901 MOV DX,0109
0ABD:0105 CD21 INT 21
0ABD:0107 CD20 INT 20
В регистр DX заносится адрес первого символа строки (указатель на строку).
Дизассемблируйте коды программы:
-u 100 11E
0ABD:0100 B409 MOV AH,09
0ABD:0102 BA0901 MOV DX,0109
0ABD:0105 CD21 INT 21
0ABD:0107 CD20 INT 20
0ABD:0109 57 PUSH DI
0ABD:010A 65 DB 65
0ABD:010B 206172 AND [BX+DI+72],AH
0ABD:010E 65 DB 65
0ABD:010F 207468 AND [SI+68],DH
0ABD:0112 65 DB 65
0ABD:0113 206368 AND [BP+DI+68],AH
0ABD:0116 61 DB 61
0ABD:0117 6D DB 6D
0ABD:0118 7069 JO 0183
0ABD:011A 6F DB 6F
0ABD:011B 6E DB 6E
0ABD:011C 7321 JNB 013F
0ABD:011E 240A AND AL,0A
По адресам 100h...108h находятся коды программы. Начиная с адреса 109h, идут коды строки. Коду 57h ставится в соответствие инструкция PUSH DI - это интерпретация дизассемблера. В регистре DX хранится указатель на строку символов. Используя указатель, прерывание читает все байты, начиная с адреса 109h до кода 24h, как строку символов.
Установите регистр IP = 100h, и запустите программу:
-g
We are the champions!
Program terminated normally
Программа готова к записи на диск. Присвойте программе имя:
-n champion.com
Определим размер программы. Первый код находится по адресу 100h, а последний (24h) по адресу 11Eh. Значит длина программы равна: 11Eh - 100h + 1h = 1Fh байт. Занесите размер программы в регистровую пару [BX:CX]: BX = 0, CX = 1F. Запишите программу на диск:
-w
Writing 0001F bytes
Покиньте Debug, и проверьте работу программы Champion.com.
Напишите программы, которые выводят на экран следующие строки:
- Люк в сеть открыт...
- Virus attack!
- Работа выполнена,
пора отдыхать!
В третьем задании для перевода строки используйте коды 0Ah, 0Dh. Таблица ASCII кодов
Редактирование строк
Использовать команду "E", для ввода или редактирования строки, очень неудобно. Быстро отредактировать строку в COM-файле позволяет текстовый редактор, поддерживающий DOS кодировку. Например, в FAR: ставим курсор на файл Champion.com и жмём клавишу [F4]. В результате откроется окно редактора с символьным представлением кодов программы:
┤ ║ ☺═!═ We are the champions!$
Измените строку "We are the champions!" на любую другую, и сохраните изменения [F2]. При редактировании помните: символы слева от строки являются кодами программы, а знак $ является признаком конца строки. Все остальное можно менять без последствий.
|