комментарии к программе

Низкоуровневое программирование портов, микроконтроллеров и т.д.

Модератор: Andy

Ответить
Kaktys1991
Сообщения: 3
Зарегистрирован: 17 ноя 2009, 16:11

Помогите пожалуйста прокомментировать первую часть программы:

.model small
.data
;закодированное изображение
content db 'Фрегат'
content_sz equ $-content ;размер текста

fontname db '16x10.f',0 ;растровый шрифт, где на каждую букву хранится матрица 16x10, которая и содержит попиксельное представление символа
;
open_err db 10,13,'Open error$'
seek_err db 10,13,'Seek error$'
read_err db 10,13,'Read error$'

tdx dw ? ;временно хранится y

letter dw 10 dup (?)
txt_last dw ?
txt db 32*10*8 dup (?)

font_H equ 16
.stack 256
.code
start: mov ax, @data ;инициализируем сегментные регистры
mov ds, ax
mov es, ax

mov ax, 3d00h
mov dx, offset fontname
int 21h
jnc read_init
mov dx, offset open_err
jmp err_msg

read_init:
mov bx, ax
mov si, offset content
mov di, offset txt
mov cx, content_sz

read_loop:
push cx
xor ax, ax
lodsb
mov cx, 20
mul cx
mov dx, ax
xor cx, cx
mov ax, 4200h
int 21h
jnc read
mov dx, offset seek_err
jmp err_msg

read:
mov ah, 3fh
mov cx, 20
mov dx, offset letter
int 21h
jnc decode
mov dx, offset read_err
jmp err_msg

decode:
push si
mov si, offset letter
mov cx, 10
l1:
lodsw
mov dx, 8000h
push cx
mov cx, 16
l2:
test ax, dx
jnz i1
mov byte ptr [di], 0
jmp i2
i1:
mov byte ptr [di], 3
i2:
inc di
shr dx, 1
loop l2
pop cx
loop l1
pop si
pop cx
loop read_loop

mov txt_last, di
mov ah, 3eh
int 21h

mov ax, 0a000h
mov es, ax
mov ax, 0013h
int 10h ;устанавливаем видеорежим 320*240*256 цветов
mov cx, 38400 ;очищаем экран
xor ax, ax
xor di, di
rep stosw
mov bx, 1 ;коэффициент масштабирования
m2: call scaled_text;выволим картинку с заданным масштабом
inc bx ;увеличиваем масштаб
in al, 60h ;читаем из порта клавиатуры
cmp al, 1 ;если нажата ESC, то выход
jz ex
call waitp ;задержка
cmp bx, 7 ;достигли максимального масштаба
jnz m2 ;если нет, продолжаем
dec bx ;корректируем масштаб
m3: call scaled_text;выволим картинку с заданным масштабом
dec bx ;увеличиваем масштаб
call waitp ;ожидание
cmp bx, 0 ;достигли минимального масштаба?
jnz m3 ;если нет, продолжаем
inc bx ;корректируем масштаб
jmp m2 ;начинаем сначала

err_msg:
mov ah, 09
int 21h

ex: mov ax, 4c00h ;выход из программы
int 21h

waitp: push cx ;подпрограмма задержки выполнения программы
push dx
mov dx, 6000 ;Поскольку у меня не работает функция 86h int 16h(задержка)
llp1: xor cx, cx
llp: loop llp ;внутренний цикл ожидания
in al, 60h ;читаем из порта клавиатуры
cmp al, 1 ;если нажата ESC, то выход
jz ex
;то будем приостанавливать программу при помощи циклов ожидания
dec dx
jnz llp1 ;внешниq цикл ожидания
pop dx
pop cx
ret

scaled_text: ;вывод в центре экрана отмасштабированой картинки. bx - масштаб
mov si, offset txt;начало картинки

mov ax, txt_last
sub ax, offset txt
xor dx, dx
mov cx, font_H
div cx ;длина строки картинки
mul bx ;умножаем масштаб на длину строки
mov cx, 320
sub cx, ax
jge work
ret
work:
shr cx, 1 ;получаем коорд левого угла отмасштабир картинки, выводивой в центр экрана

mov ax, font_H
mul bx
mov dx, 200
sub dx, ax
shr dx, 1 ;получаем коорд верхнего угла отмасштабир картинки, выводивой в центр экрана
mov tdx, dx ;сохраняем dх

push cx
mov cx, 38400 ;очищаем экран
xor ax, ax
xor di, di
rep stosw
pop cx

xor di, di ;счетчис столбца картинки
lp: cmp si, txt_last; проверяем достигли ли конца картинки
jz skip ;если достигли, то заканчиваем вывод
lodsb ;берем байт(пиксель) из картинки
inc di ;увеличиваем счетчик столбцов
call scaled_pixel;выводим отмасштабированый пиксель
add dx, bx ;переходим к следующей горизонтальной координате
cmp di, font_H ;если закончиласть строка картинки
jnz m1
xor di, di ;то обнулить счетчик
mov dx, tdx ;восстановить сх
add cx, bx ;увеличикаем координату y

m1: jmp lp ;продолжаем вывод
skip: ret ;выход из подпрограммы

;подпрограмма вывода отмасштабированного пикселя
scaled_pixel:
push di ;сохраняем регистры
push si
push dx
push cx
push bx
push ax
mov si,bx ;сохраняем масштаб
mov ax,320
mul dx ;y*320
add ax,cx ;y*320+х
mov di,ax ;получили адрес верхнего левого угола квадратика
pop ax ;восстанавливаем цвет пикселя
pxlp: mov cx,si ;количество пикселей погориз=масштабу
push di ;сохраняем адрес верхнего левого угола квадратика
rep stosb ;выводим строку пикселей из квадратика
pop di ;восстанавливаем адрес верхнего левого угола квадратика
add di,320 ;переходим на следующую строку
dec bx ;уменьшаем количество оставшихся строк
jnz pxlp ;продолжаем пока не выведем все
pop bx ;восстановить регистры
pop cx
pop dx
pop si
pop di
ret ;выход
end start
Kaktys1991
Сообщения: 3
Зарегистрирован: 17 ноя 2009, 16:11

Всё! Всё готово. Если кому интересно, то вот программа по масштабированию любого текста и символов. Писал не сам, но могу помочь связаться с программистом.

.model small
.data

; ---- константы, связанные с генерацией изображения
content db 'Фрегат' ; текст для отображения в виде изображения
content_sz equ $-content ; размер текста (т.е. текущий адрес минус адрес начала)

fontname db '16x10.f',0 ; имя файла со шрифтом
font_H equ 16 ; константа - высота фонта

; ---- сообшения об ошибках файловых операций
open_err db 10,13,'Open error$'
seek_err db 10,13,'Seek error$'
read_err db 10,13,'Read error$'

; ---- рабочие поля и буфера
tdx dw ? ;временно хранится y в процессе отрисовки

letter dw 10 dup (?) ; буфер для считывания одной литеры из файла шрифтов

txt_last dw ? ; адрес первого свободного байта (для вычисления длины изображения)
txt db 32*10*8 dup (?) ; здесь будет закодированное изображение

.stack 256
.code
start:
; ---- загрузка сегментных регистров
mov ax, @data ; инициализируем сегментные регистры
mov ds, ax
mov es, ax ; (на этапе генерации изображения ds = es = @data)

; ---- открытие файла
mov ax, 3d00h ; ah = 3d - функция open file, al = 0 - режим чтения
mov dx, offset fontname ; ds:dx - имя файла (с завершающим нулем)
int 21h ; прерывание DOS Services
jnc read_init ; продолжаем, если нет ошибки
mov dx, offset open_err ; иначе загрузим адрес сообщения
jmp err_msg ; и на выход

; ---- инициализация цикла по тексту
read_init:
mov bx, ax ; handle открытого файла (всё время будет в BX)
mov si, offset content ; указатель входного текста
mov di, offset txt ; указатель выходного буфера
mov cx, content_sz ; счетчик байт входного текста

; ---- начало цикла по тексту
read_loop:
push cx ; сохраняем счетчик цикла
; вычисление смещения в файле
xor ax, ax ; обнулим регистр
lodsb ; загрузим очередной символ
mov cx, 20 ; умножим на 20 (размеродного символа)
mul cx
; сдвиг указателя файла
mov dx, ax ; dx - получили младшие разряды смещения
xor cx, cx ; cx - обнулим старшие разряды смещения
mov ax, 4200h ; ah = 42 - функция seek file, al = 0 - смещение от начала
int 21h ; прерывание DOS Services
jnc read ; продолжаем, если нет ошибки
mov dx, offset seek_err ; иначе загрузим адрес сообщения
jmp err_msg ; и на выход

; чтение файла
read:
mov ah, 3fh ; ah = 3f - функция read file
mov cx, 20 ; cx - количество байт для чтения
mov dx, offset letter ; ds:dx - буфер для чтения
int 21h ; прерывание DOS Services
jnc decode ; продолжаем, если нет ошибки
mov dx, offset read_err ; иначе загрузим адрес сообщения
jmp err_msg ; и на выход

; инициализация цикла декодирования символа шрифта
decode:
push si
mov si, offset letter ; указатель на буфер шрифта
mov cx, 10 ; число столбцов в символе
; внешний цикл по столбцам символа
l1:
lodsw ; загружаем битовую маску столбца
mov dx, 8000h ; начальная битовая маска для развертки
push cx ; сохраняем счетчик цикла
mov cx, 16 ; счетчик цикла для развертки

; внутренний цикл - развертка одного столбца символа
l2:
test ax, dx ; проверка очередного бита
jnz i1
mov byte ptr [di], 0 ; сохраняем нулевой пиксель
jmp i2
i1:
mov byte ptr [di], 3 ; сохраняем единичный пиксель
i2:
inc di ; смещаемся по выходному буферу
shr dx, 1 ; сдвигаем маску на 1 бит
loop l2 ; цикл
pop cx ; восстанавливаем счетчик предыдущего цикла
loop l1 ; цикл
pop si
pop cx ; восстанавливаем счетчик предыдущего цикла
loop read_loop ; цикл

; завершение работы с файлом
mov txt_last, di ; сохраняем адрес первого свободного байта
mov ah, 3eh ; ah = 3e - функция close file
int 21h ; прерывание DOS Services

; ---- графическая часть программы
mov ax, 0a000h ; сегмент видеопамяти
mov es, ax
mov ax, 0013h ; устанавливаем видеорежим 320*240*256 цветов
int 10h ; прерывание BIOS Video Services
mov cx, 38400 ; очищаем экран прчмой записью в видеопамять
xor ax, ax
xor di, di
rep stosw
mov bx, 1 ; начальный коэффициент масштабирования

; ---- цикл увеличения изображения
m2: call scaled_text ; выволим картинку с заданным масштабом
inc bx ; увеличиваем масштаб
in al, 60h ; читаем из порта клавиатуры
cmp al, 1 ; если нажата ESC, то выход
jz ex
call waitp ; задержка
cmp bx, 7 ; достигли максимального масштаба
jnz m2 ; если нет, продолжаем
dec bx ; корректируем масштаб
Ответить