|
[Назад] [Далее] | |
На примере первой программы на ассемблере мы уже познакомились с одним из способов вывода текста на экран — вызовом функции DOS 09h. Это далеко не единственный способ вывода текста — DOS предоставляет для этого несколько функций.
Функция DOS 02h — Записать символ в STDOUT с проверкой на Ctrl-Break
Ввод: | АН = 02h DL = ASCII-код символа |
Вывод: | Никакого, согласно документации, но на самом деле: AL = код последнего записанного символа (равен DL, кроме случая, когда DL = 09h (табуляция), тогда в AL возвращается 20h). |
Эта функция при выводе на экран обрабатывает некоторые управляющие символы — вывод символа BEL (07h) приводит к звуковому сигналу, символ BS (08h) приводит к движению курсора влево на одну позицию, символ НТ (09h) заменяется на несколько пробелов, символ LF (0Ah) опускает курсор на одну позицию вниз, и CR (0Dh) приводит к переходу на начало текущей строки.
Если в ходе работы этой функции была нажата комбинация клавиш Ctrl-Break, вызывается прерывание 23h, которое по умолчанию осуществляет выход из программы.
Например, напишем программу, выводящую на экран все ASCII-символы, 16 строк по 16 символов в строке.
; dosoutl.asm ; Выводит на экран все ASCII-символы ; .model tiny .code org 100h ; начало СОМ-файла start: mov ex,256 ; вывести 256 символов mov dl,0 ; первый символ - с кодом 00 mov ah,2 ; номер функции DOS "вывод символа" cloop: int 21h ; вызов DOS inc dl ; увеличение DL на 1 - следующий символ test dl,0Fh ; если DL не кратен 16, jnz continue_loop ; продолжить цикл, push dx ; иначе: сохранить текущий символ mov dl,0Dh ; вывести CR int 21h mov dl,0Ah ; вывести LF int 21h pop dx ; восстановить текущий символ continue_loop: loop cloop ; продолжить цикл ret ; завершение СОМ-файла end start
Это программа типа СОМ, и компилироваться она должна точно так же, как hello-1.asm в разделе 4.1. Здесь с помощью команды LOOP оформляется цикл, выполняющийся 256 раз (значение регистра СХ в начале цикла). Регистр DL содержит код символа, который равен нулю в начале цикла и увеличивается каждый раз на 1 командой INC DL. Если значение DL сразу после увеличения на 1 кратно 16, оно временно сохраняется в стеке и на экран выводятся символы CR и LF, выполняющие переход на начало новой строки. Проверка выполняется командой TEST DL,0Fh — результат операции AND над DL и 0Fh будет нулем, только если младшие четыре бита DL равны нулю, что и соответствует кратности шестнадцати.
Все функции DOS вывода на экран используют устройство STDOUT, стандартный вывод. Это позволяет перенаправлять вывод программы в файл или на стандартный ввод другой программы. Например, если написать в командной строке
hello-1.com > hello-1.out
то на экран ничего выдано не будет, а в текущем каталоге появится файл hello-1.out, содержащий строку «Hello World!». Точно так же, если написать
dosout1.com > dosout1.out
то в файле dosout1.out окажутся все символы ASCII, причем символы BEL и BS не будут интерпретироваться и запишутся в файл как есть. Символы CR и LF тоже запишутся как есть, но так как они отмечают конец строки, редакторы и просмотрщики текстовых файлов будут разрывать первую строку символов.
Функция DOS 06h — Записать символ в STDOUT без проверки на Ctrl-Break
Ввод: | АН = 06h DL = ASCII-код символа (кроме FFh) |
Вывод: | Никакого, согласно документации, но на самом деле: AL = код записанного символа (копия DL) |
Эта функция не обрабатывает управляющие символы (CR, LF, HT и BS выполняют свои функции при выводе на экран, но сохраняются при перенаправлении вывода в файл) и не проверяет нажатие Ctrl-Break. Можно заменить в программе dosoutl.asm команду MOV АН,2 на MOV АН,6 и перекомпилировать этот пример, чтобы получить более полную таблицу символов.
Функция DOS 09h — Записать строку в STDOUT с проверкой на Ctrl-Break
Ввод: | АН = 09h DS:DX = адрес строки, заканчивающейся символом $ (24h) |
Вывод: | Никакого, согласно документации, но на самом деле: AL = 24h (код последнего символа) |
Действие этой функции полностью аналогично действию функции 02h, но выводится не один символ, а целая строка, как в программах hello-1.asm и hello-2.asm.
Функция DOS 40h — Записать в файл или устройство
Ввод: | АН = 40h ВХ = 1 для STDOUT или 2 для STDERR DS:DX = адрес начала строки СХ = длина строки |
Вывод: | CF = 0, АХ = число записанных байт |
Эта функция предназначена для записи в файл, но, если в регистр ВХ поместить число 1, функция 40h будет выводить данные на STDOUT, а если ВХ = 2 — на устройство STDERR. STDERR всегда выводит данные на экран и не перенаправляется в файлы. На этой функции основаны используемые в С функции стандартного вывода — фактически функция С fputs() просто вызывает это прерывание, помещая свой первый аргумент в ВХ, адрес строки (второй аргумент) — в DS:DX и длину — в СХ.
; dosout2.asm ; Выводит на экран строку "This function can print $", ; используя вывод в STDERR, так что ее нельзя перенаправить в файл. .model tiny .code org 100h ; начало СОМ-файла start: mov ah,40h ; номер функции DOS mov bx,2 ; устройство STDERR mov dx,offset message ; DS:DX - адрес строки mov cx, message_length ; CX - длина строки int 21h ret ; завершение СОМ-файла message db "Эта функция может выводить знак $" message_length = $-message ; длина строки = текущий адрес ; минус адрес начала строки end start
Если скомпилировать эту программу и запустить ее командой
dosout2.com > dosout2.out
то сообщение появится на экране, а файл dosout2.out окажется пустым.
И наконец, последняя функция DOS вывода на экран — недокументированное прерывание 29h.
INT 29h: Быстрый вывод символа на экран
Ввод: | AL = ASCII-код символа |
В большинстве случаев INT 29h просто немедленно вызывает функцию BIOS «вывод символа на экран в режиме телетайпа», так что никаких преимуществ, кроме экономии байт при написании как можно более коротких программ, она не имеет.