Assembler - язык неограниченных возможностей

         

Прямая работа с видеопамятью


Все, что изображено на мониторе — и графика, и текст, одновременно присутствует в памяти, встроенной в видеоадаптер. Для того чтобы изображение появилось на мониторе, оно должно быть записано в память видеоадаптера. Для этого отводится специальная область памяти, начинающаяся с абсолютного адреса B800h:0000h (для текстовых режимов) и заканчивающаяся на B800h:FFFFh. Все, что программы пишут в эту область памяти, немедленно пересылается в память видеоадаптера. В текстовых режимах для хранения каждого изображенного символа используются два байта: байт с ASCII-кодом символа и байт с его атрибутом, так что по адресу B800h:0000h лежит байт с кодом символа, находящимся в верхнем левом углу экрана; по адресу B800h:0001h лежит атрибут этого символа; по адресу B800h:0002h лежит код второго символа в верхней строке экрана и т.д.

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

; dirout.asm ; Выводит на экран все ASCII-символы без исключения, ; используя прямой вывод на экран .model tiny .code .386 ; будет использоваться регистр ЕАХ ; и команда STOSD org 100h ; начало СОМ-файла start: mov ax,0003h int 10h ; видеорежим 3 (очистка экрана) cld ; обработка строк в прямом направлении ; подготовка данных для вывода на экран mov еах,1F201F00h ; первый символ 00 с атрибутом 1Fh, ; затем пробел (20h) с атрибутом 1Fh mov bx,0F20h ; пробел с атрибутом 0Fh mov cx,255 ; число символов минус 1 mov di,offset ctable ; ES:DI - начало таблицы cloop: stosd ; записать символ и пробел в таблицу ctable inc al ; AL содержит следующий символ test cx,0Fh ; если СХ не кратен 16, jnz continue_loop ; продолжить цикл, push cx ; иначе: сохранить значение счетчика mov cx,80-32 ; число оставшихся до конца строки символов xchg ax,bx rep stosw ; заполнить остаток строки пробелами ; с атрибутом 0F xchg bx.ax ; восстановить значение ЕАХ pop cx ; восстановить значение счетчика continue_loop: loop cloop


stosd ; записать последний (256-й) символ и пробел

; собственно вывод на экран mov ax,0B800h ; сегментный адрес видеопамяти mov es,ax xor di,di ; DI = 0, адрес начала видеопамяти в ES:DI mov si,offset ctable ; адрес таблицы в DS:SI mov cx,15*80+32 ; 15 строк по 80 символов, последняя строка - 32 rep movsw ; скопировать таблицу ctable в видеопамять ret ; завершение СОМ-файла ctable: ; Данные для вывода на экран начинаются сразу ; за концом файла. В ЕХЕ-файле такие данные ; определяют в сегменте .data? end start

При подготовке данных для копирования в видеопамять в этой программе использовался тот факт, что в архитектуре Intel при записи слова (или двойного слова) в память старший байт располагается по старшему адресу. Так что при записи в память двойного слова 1F201F00h сначала записывается самый младший байт 00h (ASCII-код текущего символа), потом 1Fh, используемый в этом примере атрибут, потом 20h (код пробела) и потом, по самому старшему адресу, — самый старший байт, 1Fh, атрибут для этого пробела. Кроме того, в этом примере использовались некоторые 32-битные команды (MOV и STOSD). Этими командами можно пользоваться из 16-битной программы (разумеется, если процессор 80386 и выше), но не стоит этим злоупотреблять, так как каждая такая команда оказывается длиннее на 1 байт и выполняется дольше на 1 такт.


Содержание раздела