Чтобы использовать целочисленную арифметику, умножим tg и
EPS на (X2-X1)*2 :
TG = (Y2 - Y1) а условие приращения Y: EPS > (X2 - X1)
Итак, теперь
TG=(y2-y1)*2;
EPS=0;
lamb=(x2-x1)*2;
y=y1;
for (x=x1; x<=x2; x++)
{ pixel(x,y);
EPS+=TG
if(EPS>(x2-x1)){y++;EPS-=lamb}
}
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
Start: jmp start1
color db 0 ; Текущий цвет
x1 dw 0 ; Координата Х1
y1 dw 0 ; Координата У1
x2 dw 0 ; Координата Х2
y2 dw 0 ; Координата У2
lamb dw 0 ; Коэффициент лямбда
tg dw 0 ; Наклон прямой
start1: ; Установка видеорежима
mov ah,0 ; Функция установки видеорежима
mov al,4 ; Граф. реж. CGA 320 * 200 точек
int 10h
; Построение линии X1,Y1 - X2,Y2
mov color,3 ; Цвет белый
mov x1,20
mov y1,15
mov x2,300
mov y2,60
call line
call kbin
int 20h
; Построение линии
; X1,Y1 - координаты начала линии
; X2,Y2 - координаты конца линии
line proc near
mov ax,x2
sub ax,x1 ; X2 - X1
mov si,ax ; SI = X2-X1
shl ax,1 ; * 2
mov lamb,ax ; Лямбда в переменную
mov ax,y2
sub ax,y1 ; Y2 - Y1
shl ax,1 ; * 2
mov tg,ax ; Наклон в переменную
xor bp,bp ; Погрешность
mov dx,y1
mov cx,x1
line1: call pixel
add bp,tg
cmp si,bp ; (X2-X1) : D
jge line2 ; D <= (X2-X1)
; D > (X2-X1)
inc dx ; Y=Y+1
sub bp,lamb ; D=D-lamb
line2: inc cx
cmp cx,x2
jnz line1
ret
line endp
; Ввод с клавиатуры
kbin proc near
mov ah,0 ; Функция 0
int 16h ; клавиатурного прерывания
ret
kbin endp
; Построение точки текущего цвета
; CX - координата Х
; DX - координата Y
pixel proc near
push bx
mov al,color
mov ah,0ch ; Функция построения графич. точки
mov bh,0 ; Видеостраница
int 10h
pop bx
ret
pixel endp
code ends
END Start ; Указание точки входа в программу
Написать программу, рисующую прямую линию с произвольным наклоном. Для этого надо:
· определить, какая переменная X или Y является независимой
· определить знак приращения X и Y
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
Start: jmp start1
color db 0 ; Текущий цвет
x1 dw 0 ; Координата Х1
y1 dw 0 ; Координата У1
x2 dw 0 ; Координата Х2
y2 dw 0 ; Координата У2
x_inc dw 0 ; Приращение Х
y_inc dw 0 ; Приращение Y
ddy dw 0 ; Y2 - Y1
ddx dw 0 ; X2 - X1
lamb dw 0 ; Коэффициент лямбда
tg dw 0 ; Наклон прямой
start1: ; Установка видеорежима
mov ah,0 ; Функция установки видеорежима
mov al,4 ; Граф. реж. CGA 320 * 200 точек
int 10h
; Построение линии X1,Y1 - X2,Y2
mov color,3 ; Цвет белый
mov x1,160
mov y1,100
mov x2,60
mov y2,10
call line
call kbin
int 20h
; Построение линии
; X1,Y1 - координаты начала линии
; X2,Y2 - координаты конца линии
line proc near
; Определение знака приращения Y
mov ax,y2
cmp ax,y1
jnc line01 ; y1 <= y2
; y2 < y1 - отрицательное приращение
mov y_inc,-1
mov bx,y1
sub bx,ax ; Y1 - Y2
mov ddy,bx ; abs(Y2-Y1)
jmp line02
line01: mov y_inc,1 ; Положительное приращение
sub ax,y1 ; Y2 - Y1
mov ddy,ax ; abs(Y2-Y1)
; Определение знака приращения X
line02: mov ax,x2
cmp ax,x1
jnc line03 ; x1 <= x2
; x2 < x1 - отрицательное приращение
mov x_inc,-1
mov bx,x1
sub bx,ax ; X1 - X2
mov ddx,bx ; abs(X2-X1)
jmp line04
line03: mov x_inc,1 ; Положительное приращение
sub ax,x1 ; X2 - X1
mov ddx,ax ; abs(X2-X1)
; Определение независимой переменной
line04: mov ax,ddx
cmp ax,ddy
jnc line1 ; (Y2-Y1) < (X2-X1)
jmp line2 ; (Y2-Y1) > (X2-X1)
; Построение при (Y2-Y1) < (X2-X1)
line1: mov ax,ddx ; ax = X2-X1
mov si,ddx ; SI = X2-X1
shl ax,1 ; * 2
mov lamb,ax ; Лямбда в переменную
mov ax,ddy
shl ax,1 ; * 2
mov tg,ax ; Наклон в переменную
xor bp,bp ; Погрешность
mov dx,y1
mov cx,x1
line11: call pixel
add bp,tg
cmp si,bp ; (X2-X1) : D
jge line12 ; D <= (X2-X1)
; D > (X2-X1)
add dx,y_inc ; Y=Y+1
sub bp,lamb ; D=D-lamb
line12: add cx,x_inc
cmp cx,x2
jnz line11
ret
; Построение при (Y2-Y1) > (X2-X1)
line2: mov ax,ddy ;ax = Y2 - Y1
mov si,ax ; SI = Y2 - Y1
shl ax,1 ; * 2
mov lamb,ax ; Лямбда в переменную
mov ax,ddx
shl ax,1 ; * 2
mov tg,ax ; Наклон в переменную
xor bp,bp ; Погрешность
mov dx,y1
mov cx,x1
line21: call pixel
add bp,tg
cmp si,bp ; (Y2-Y1) : D
jge line22 ; D <= (Y2-Y1)
; D > (X2-X1)
add cx,x_inc
sub bp,lamb ; D=D-lamb
line22: add dx, y_inc
cmp dx,y2
jnz line21
ret
line endp
; Ввод с клавиатуры
kbin proc near
mov ah,0 ; Функция 0
int 16h ; клавиатурного прерывания
ret
kbin endp
; Построение точки текущего цвета
; CX - координата Х
; DX - координата Y
pixel proc near
push bx
mov al,color
mov ah,0ch ; Функция построения графич. точки
mov bh,0 ; Видеостраница
int 10h
pop bx
ret
pixel endp
code ends
END Start ; Указание точки входа в программу
2.1.4. Вывод динамических изображений
Написать программу, которая в графическом режиме CGA 4 * 320 * 200 рисует фигурку колобка размером 16 * 16 точек непосредственно в экранной области и перемещает его при нажатии курсорных клавиш. Коды управления курсором: Вверх - 48h, Вниз - 50h, Вправо - 4Dh, Влево - 4Bh.
Структура видеопамяти в режиме CGA: начинается с адреса B000h, четные линии имеют смещение 0000h - 1F3Fh (около 8 КВ), нечетные 2000h - 3F3Fh (около 8 КВ) (промежуток между ними не используется).
Самая левая точка из четырех | |||||||||||
Самая правая точка из четырех | |||||||||||
Биты |
Цвет 00 - черный
01 - голубой (зеленый)
10 - сиреневый (красный)
11 - белый (желтый)
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
Start: jmp start1
addr dw 0 ; Адрес начальной точки спрайта
addr0 dw 0 ; Старый адрес
; 16 * 16
colob db 0,5,50h,0
db 0,5fh,0f5h,0
db 5,0ffh,0ffh,50h
db 3fh,0ffh,0ffh,0fch
db 0ffh,0afh,0fah,0ffh
db 0ffh,0abh,0eah,0ffh
db 0ffh,8bh,0e2h,0ffh
db 0ffh,0ffh,0ffh,0ffh
db 3fh,0beh,0beh,0fch
db 0fh,0efh,0fbh,0f0h
db 0,0fah,0afh,0
db 0,3fh,0fch,0
db 0,3ch,3ch,0
db 15h,3ch,3ch,54h
db 55h,54h,15h,55h
db 55h,54h,15h,55h
start1: ; Установка видеорежима
mov ah,0 ; Функция установки видеорежима
mov al,4 ; Граф. реж. CGA 320 * 200 точек
int 10h
mov di,addr
st2: lea si,colob
call sprit0
call sprite
; Сохранение исходных координат
mov ax,addr
mov addr0,ax
; Чтение клавиатуры
call kbin
cmp ah,1 ; Скан-код = Esc ?
jnz st3 ; Нет
int 20h ; Выход при нажатии Esc
st3: cmp ah,48h ; Вверх ?
jnz st4
sub addr,80*2 ; Вверх на 4 строки
jmp st2
st4: cmp ah,50h ; Вниз ?
jnz st5
add addr,80*2 ; Вниз на 4 строки
jmp st2
st5: cmp ah,4dh ; Вправо ?
jnz st6
inc addr
jmp st2
st6: cmp ah,4bh ; Влево ?
jnz st2
dec addr
jmp st2
; Ввод с клавиатуры
kbin proc near
mov ah,0 ; Функция 0
int 16h ; клавиатурного прерывания
ret
kbin endp
; Построение спрайта 16 * 16
; addr - адрес левого верхнего угла
; SI - начало спрайта
sprite proc near
; Построение четных строк
push si
mov di,addr
mov ax,0b800h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp1: mov cx,4 ; Счетчик числа слов
rep movsb
add di,76
add si,4
dec bp
jnz sp1
; Построение нечетных строк
mov di,addr
pop si
add si,4 ; Переход к нечетной строке
mov ax,0ba00h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp2: mov cx,4 ; Счетчик числа слов
rep movsb
add di,76
add si,4
dec bp
jnz sp2
ret
sprite endp
; Стирание спрайта 16 * 16
; addr0 - координаты левого верхнего угла
sprit0 proc near
; Стирание четных строк
mov di,addr0
mov ax,0b800h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
xor al,al
sp3: mov cx,4 ; Счетчик числа слов
rep stosb
add di,76
dec bp
jnz sp3
; Стирание нечетных строк
mov di,addr0
mov ax,0ba00h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp4: mov cx,4 ; Счетчик числа слов
rep stosb
add di,76
dec bp
jnz sp4
ret
sprit0 endp
code ends
END Start ; Указание точки входа в программу
Изменить палитру на красный-зеленый-желтый. При движении менять проекции фигурки. Палитра переключается в режиме 4:
int 10h, функция 0Bh
BH=1, BL=палитра (0, 1)
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
Start: jmp start1
addr dw 0 ; Адрес начальной точки спрайта
addr0 dw 0 ; Старый адрес
; 16 * 16
colf db 0,5,50h,0
db 0,5fh,0f5h,0
db 5,0ffh,0ffh,50h
db 3fh,0ffh,0ffh,0fch
db 0ffh,0afh,0fah,0ffh
db 0ffh,0abh,0eah,0ffh
db 0ffh,8bh,0e2h,0ffh
db 0ffh,0ffh,0ffh,0ffh
db 3fh,0beh,0beh,0fch
db 0fh,0efh,0fbh,0f0h
db 0,0fah,0afh,0
db 0,3fh,0fch,0
db 0,3ch,3ch,0
db 15h,3ch,3ch,54h
db 55h,54h,15h,55h
db 55h,54h,15h,55h
colb db 0,5,50h,0
db 0,55h,55h,0
db 5,55h,55h,50h
db 15h,55h,55h,54h
db 0d5h,55h,55h,57h
db 0d5h,55h,55h,57h
db 0f5h,55h,55h,5fh
db 0fdh,55h,55h,7fh
db 3dh,55h,55h,7ch
db 0fh,55h,55h,0f0h
db 0,0ffh,0ffh,0
db 0,3fh,0fch,0
db 0,3ch,3ch,0
db 15h,3ch,3ch,54h
db 55h,54h,15h,55h
db 55h,54h,15h,55h
coll db 0,5,50h,0
db 0,5fh,55h,50h
db 5,7fh,55h,50h
db 1,0ffh,0fdh,54h
db 2,0ffh,0ffh,55h
db 2,0bfh,0ffh,55h
db 0fch,0bfh,0ffh,0d5h
db 0ffh,0ffh,0ffh,0f5h
db 0fh,0ffh,0bfh,0fch
db 3,0feh,0ffh,0f0h
db 0,0abh,0ffh,0
db 0,3fh,0fch,0
db 0,0fh,0fch,0
db 15h,0fh,0fch,0
db 55h,55h,55h,0
db 55h,55h,55h,0
colr db 0,5,50h,0
db 0,55h,0f5h,0
db 5,55h,0fdh,50h
db 15h,7fh,0ffh,40h
db 55h,0ffh,0ffh,80h
db 55h,0ffh,0feh,80h
db 57h,0ffh,0feh,3fh
db 3fh,0ffh,0ffh,0ffh
db 3fh,0feh,0ffh,0f0h
db 0fh,0ffh,0bfh,0c0h
db 0,0ffh,0eah,0
db 0,3fh,0fch,0
db 0,3fh,0f0h,0
db 0,3fh,0f0h,54h
db 0,55h,55h,55h
db 0,55h,55h,55h
start1: ; Установка видеорежима
mov ah,0 ; Функция установки видеорежима
mov al,5 ; Граф. реж. CGA 320 * 200 точек
int 10h
mov ah,0bh ; Установка палитры
mov bx,102h
int 10h
mov di,addr
lea si,colf
st2: call sprit0
call sprite
; Сохранение исходных координат
st0: mov ax,addr
mov addr0,ax
; Чтение клавиатуры
call kbin
cmp ah,1 ; Скан-код = Esc ?
jnz st3 ; Нет
int 20h ; Выход при нажатии Esc
st3: cmp ah,48h ; Вверх ?
jnz st4
sub addr,80*2 ; Вверх на 4 строки
lea si,colb
jmp st2
st4: cmp ah,50h ; Вниз ?
jnz st5
add addr,80*2 ; Вниз на 4 строки
lea si,colf
jmp st2
st5: cmp ah,4dh ; Вправо ?
jnz st6
inc addr
lea si,colr
jmp st2
st6: cmp ah,4bh ; Влево ?
jnz st0
dec addr
lea si,coll
jmp st2
; Ввод с клавиатуры
kbin proc near
mov ah,0 ; Функция 0
int 16h ; клавиатурного прерывания
ret
kbin endp
; Построение спрайта 16 * 16
; addr - адрес левого верхнего угла
; SI - начало спрайта
sprite proc near
; Построение четных строк
push si
mov di,addr
mov ax,0b800h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp1: mov cx,4 ; Счетчик числа слов
rep movsb
add di,76
add si,4
dec bp
jnz sp1
; Построение нечетных строк
mov di,addr
pop si
add si,4 ; Переход к нечетной строке
mov ax,0ba00h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp2: mov cx,4 ; Счетчик числа слов
rep movsb
add di,76
add si,4
dec bp
jnz sp2
ret
sprite endp
; Стирание спрайта 16 * 16
; addr0 - координаты левого верхнего угла
sprit0 proc near
; Стирание четных строк
mov di,addr0
mov ax,0b800h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
xor al,al
sp3: mov cx,4 ; Счетчик числа слов
rep stosb
add di,76
dec bp
jnz sp3
; Стирание нечетных строк
mov di,addr0
mov ax,0ba00h
mov es,ax
mov bp,8 ; Счетчик числа строк/2
sp4: mov cx,4 ; Счетчик числа слов
rep stosb
add di,76
dec bp
jnz sp4
ret
sprit0 endp
code ends
END Start ; Указание точки входа в программу
РАБОТА С ДИСКАМИ
2.2.1. Работа с гибкими дисками
Написать программу, которая записывает 6-байтовый пароль на 40 дорожку ключевой дискеты.записано то, что надо.
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
disk equ 0 ; Диск А
golovka equ 0 ; Гловка 0
dorojka equ 40 ; Дорожка 10
sector_track equ 15 ; Секторов на дорожке
sector equ 15 ; Номер сектора
.286
Start: jmp start1
Buffer db 'ququ',251 dup (?)
db '1$'
buffer_format db 40,0,1,1 ; Дор., гол., сект., код сект
db 40,0,2,1
db 40,0,3,1
db 40,0,4,1
db 40,0,5,1
db 40,0,6,1
db 40,0,7,1
db 40,0,8,1
db 40,0,9,1
db 40,0,10,1
db 40,0,11,1
db 40,0,12,1
db 40,0,13,1
db 40,0,14,1
db 40,0,15,1
err_set db 0dh,0ah,0ah,'Ошибка установки типа дискеты',0dh,0ah,'$'
err_read db 0dh,0ah,0ah,'Ошибка чтения с диска ','$'
tabl_par dw 0,0 ; Адрес таблицы параметров дискеты
start1: mov ax,cs
mov ds,ax
; Установка типа дискеты
mov ah,17h
mov al,2 ; Дискета 360 КВ в дисководе 1,2 М
mov dl,0
int 13h
jnc m1
; Сообщение об ошибке установки типа дискеты
mov ah,09
lea dx,err_set
int 21h
call rest
int 20h
; Считыание и сохранение адреса таблицы параметров
; дискеты (находится на месте вектора прерывания 1Eh)
m1: mov ah,35h
mov al,1Eh
int 21h
mov tabl_par,bx ; Смещение
mov tabl_par+2,es ; Сегмент
mov byte ptr es:[bx+3],1 ; Код размера сектора (256)
mov byte ptr es:[bx+4],sector_track ; Количество секторов
push cs
pop es
; Чтение текста из сектора
mov ah,2 ; Функция чтения сектора
mov al,1 ; Количество секторов
mov ch,dorojka ; Цилиндр
mov cl,sector ; Сектор
mov dh,golovka ; Головка
mov dl,disk ; Диск
lea bx,buffer ; Читаемый текст
int 13h
jnc m3
; Сообщение об ошибке чтения
mov ah,09
lea dx,err_read
int 21h
jmp m4
m3: mov ah,09
lea dx,buffer
int 21h
m4: call rest
int 20h
rest proc near
; Восстановление таблицы параметров дискеты
; (находится на месте вектора прерывания 1Eh)
mov ah,35h ; Взятие вектора
mov al,1Eh ; Номер вектора
int 21h
mov byte ptr es:[bx+3],2 ; Код размера сектора (512)
mov byte ptr es:[bx+4],9 ; Количество секторов
ret
rest endp
Code ENDS
END Start
Написать программу, которая проверяет наличие пароля на 40 дорожке ключевой дискеты и выводит сообщение:
· "Все в порядке", - если пароль верен,
· "Вставьте ключевую дискету" - в любом другом случае.
Assume CS: Code;, DS: Code
Code SEGMENT
org 100h
disk equ 0 ; Диск А
golovka equ 0 ; Гловка 0
dorojka equ 40 ; Дорожка 10
sector_track equ 15 ; Секторов на дорожке
sector equ 15 ; Номер сектора
.286
Start: jmp start1
Buffer db 'ququ',251 dup(?)
db '1$'
err_1 db 24 dup (0ah),0dh
db 26 dup (32),'Установите ключевую дискету!'
db 12 dup (0ah),'$'
msg_ok db 24 dup (0ah),0dh
db 30 dup (32),'Все в порядке'
db 12 dup (0ah),'$'
password db 'Пароль' ; Пароль, который будет распознаваться
tabl_par dw 0,0 ; Адрес таблицы параметров дискеты
start1: mov ax,cs
mov ds,ax
; Установка типа дискеты
mov ah,17h ; Функция определения типа дискеты
mov al,2 ; Дискета 360 КВ в дисководе 1,2 М
mov dl,0 ; Дисковод А
int 13h
jc err1 ; Переход на сообщение об ошибке
; Считыание и сохранение адреса таблицы параметров
; дискеты (находится на месте вектора прерывания 1Eh)
mov ah,35h
mov al,1Eh
int 21h
mov tabl_par,bx ; Смещение
mov tabl_par+2,es ; Сегмент
mov byte ptr es:[bx+3],1 ; Код размера сектора (256)
mov byte ptr es:[bx+4],sector_track ; Количество секторов
push cs
pop es
; Чтение текста из сектора
mov ah,2 ; Функция чтения сектора
mov al,1 ; Количество секторов
mov ch,dorojka ; Цилиндр
mov cl,sector ; Сектор
mov dh,golovka ; Головка
mov dl,disk ; Диск
lea bx,buffer ; Читаемый текст
int 13h
jc err1
; Проверка пароля
mov cx,6 ; Количество байтов в пароле
lea si,buffer+10 ; Позиция, с которой записан пароль
lea di,password ; Смещение пароля
m1: lodsb ; [si]->al
cmp al,[di] ; Сравнение с байтом пароля
jnz err1 ; Переход на сообщение об ошибке
inc di ; Переход к следующему символу в пароле
; inc si не нужен, так как он автоматически
; выполняется в команде lodsb
loop m1 ; Переход на начало цикла проверки пароля
; Все в порядке
mov ah,09 ; Функция вывода строки
lea dx,msg_ok ; Сообщение 'Все в порядке'
int 21h ; Вызов функции DOS
; Ожидание нажатия клавиши
mov ah,0 ; Функция 0
int 16h ; Клавиатурное прерывание
call rest ; Восстановление табл. парам. дискеты
int 20h ; Выход из программы
; Сообщение об ошибке
err1: mov ah,09 ; Функция 0
lea dx,err_1 ; Сообщение об ошибке
int 21h ; Вызов функции DOS
; Ожидание нажатия клавиши
mov ah,0 ; Функция 0
int 16h ; Клавиатурное прерывание
call rest ; Восстановление табл. парам. дискеты
int 20h ; Выход из программы
rest proc near
; Восстановление таблицы параметров дискеты
; (находится на месте вектора прерывания 1Eh)
mov ah,35h ; Взятие вектора
mov al,1Eh ; Номер вектора
int 21h
mov byte ptr es:[bx+3],2 ; Код размера сектора (512)
mov byte ptr es:[bx+4],9 ; Количество секторов
; Сброс диска 0
xor ax,ax ; Функция 0
xor dl,dl ; Дисковод А
int 21h ; Вызов функции DOS
ret
rest endp
Code ENDS
END Start
2.2.2. Работа с жестким диском
Написать программу, которая при первом запуске (инициализации) определяет начальный кластер своего расположения на диске, записывает в файл на диск этот номер и выполняет свою основную функцию - выводит сообщение на экран, что все в порядке. При повторном и последующих запусках программа должна проверять, соответствует ли записанный в ней при инициализации номер начального кластера действительному номеру. При совпадении программа должны выполнить свою основную функцию - вывести сообщение о том, что все в порядке. При несовпадении записанного в программе и действительного номеров начального кластера программа должна вывести на экран сообщение о нежелании работать.
Assume CS: Code;, DS: Code
Code SEGMENT
bpb struc ; Структура блока параметров BIOS
sect_siz dw ? ; Размер сектора в байтах
clus_siz db ? ; Секторов в кластере
res_sect dw ? ; Зарезервированных секторов
fat_num db ? ; Кол-во FAT на диске
root_siz dw ? ; Размер каталога (кол-во файлов)
num_sect dw ? ; Общее количество секторов
med_desc db ? ; Дескриптор носителя
fat_siz dw ? ; Число секторов в FAT
sec_trac dw ? ; Число секторов на дорожке
num_had dw ? ; Число головок
hidd_sec dw ? ; Число скрытых секторов
bpb ends
bpd struc ; Структура блока параметров диска
sec_num dd ? ; 32-битный номер сектора
number_s dw ? ; Количество читаемых секторов
b_off dw ? ; Смещение буфера
b_seg dw ? ; Сегмент буфера
bpd ends
cat struc ; Структура записи каталога
f_name db 11 dup (?) ; Имя файла с расширением
f_attr db ? ; Атрибуты
res_dos db 10 dup (?) ; Резерв
f_time dw ? ; Время создания
f_date dw ? ; Дата создания
b_clu dw ? ; Начальный кластер
f_size dd ? ; Размер файла
cat ends
.286
org 100h
Start: jmp st1
key dw ? ; Начальный кластер
f_key db 0 ; Флаг инициализации
err_read db 'Ошибка чтения $'
ok db 12 dup(0ah),0dh,25 dup(' ')
db 'Все в порядке',12 dup(0ah),'$'
nok db 12 dup(0ah),0dh,25 dup(' ')
db "I'm sorry",12 dup(0ah),'$'
fil_name db 'LAB2.COM',0
f_num_s dw ? ; Физ. номер сектора
sec_cyl dw ? ; Число секторов на цилиндре
sec_cat db ? ; Секторов в корневом каталоге
cyl db ? ; Цилиндр
head db ? ; Головка
beg_sec dd ? ; Нач. сектор раздела (логич.)
num_sec dw ? ; Кол. читаемых сект. каталога
point dw ? ; Указатель в тек. каталоге
flag db ? ; Флаг поиска
f_flag db ? ; Флаг поиска файла
root_s dw ? ; Лог. ном. сект. нач. корн. кат.
clu0 dw ? ; Лог. ном. первого доступн. кластера
handler dw ? ; Дескриптор файла
buf_cat db 100h dup(?),'$' ; Буфер для тек. каталога
buf1 db 200h dup(?) ; Буфер для MBR
buf2 db 200h dup(?) ; Буфер для BR
db '$'
buf3 db 800h dup(?) ; Буфер для корн.кат.
db '$'
b_param db 10 dup(0) ; Блок параметров для int 25h
st1: mov ax,cs
mov ds,ax
; Определение начального кластера
lea ax,buf_cat ; Инициализация указателя на начало
mov point,ax ; буфера текущего каталога
; Получение текущего каталога в buf_cat
mov ah,47h ; Получение текущего каталога
xor dl,dl ; Текущий дисковод
lea si,buf_cat ; Буфер для ASCIIZ тек. каталога
int 21h ; Тек' каталог в buf_cat
jnc st2 ; Ошибки нет
; Ошибка чтения сектора
lea dx,err_read
mov al,1 ; Ошибка чтения 1
call msg
int 20h
st2: ; Чтение BR в buf2
mov al,2 ; Диск С
mov cx,-1 ; Признак > 32 M
lea bx,b_param ; Блок параметров
mov word ptr [bx].sec_num,0 ; Отн. номер сектора
mov word ptr [bx+2].sec_num,0 ; Отн. номер сектора
mov [bx].number_s,1 ; Кол-во читаемых секторов
mov [bx].b_off,offset buf2
mov dx,cs
mov [bx].b_seg,dx
int 25h ; BR в buf2
pop cx
jnc st3 ; Ошибки нет
; Ошибка чтения сектора
lea dx,err_read
mov al,2 ; Второе чтение сектора
call msg
int 20h
; Чтение корневого каталога в buf3
st3: lea si,[buf2+11]
; Определение количества читаемых секторов каталога
; (один кластер, но не более 4)
mov al,[si].clus_siz ; Размер кластера
cmp al,4 ; Разм. кластера < 4
jc st31
mov al,4
st31: xor ah,ah
mov num_sec,ax ; Кол-во читаемых секторов кат.
; Определение числа секторов в корневом каталоге
mov ax,[si].root_siz ; Размер кат. (кол.файлов)
mov cl,4
shr ax,cl ; /16 (записей в секторе)
mov sec_cat,al ; Секторов в каталоге
; Определение физ. номера сектора начала корневого каталога
mov dl,[si].fat_num ; Кол-во FAT на диске
mov ax,[si].fat_siz ; Число секторов в FAT
mul dl ; AX -номер сект. нач. корнев. кат.
inc ax ; Лог. номер сектора нач. корн. кат.
mov root_s,ax ; Лог. ном. сект. нач. корн. кат.
lea bx,b_param ; Блок параметров
mov word ptr [bx].sec_num,ax ; Отн. номер сект.
mov word ptr [bx+2].sec_num,0 ; Отн. номер сект.
mov al,2 ; Диск С
mov cx,-1 ; Признак > 32 M
mov di,num_sec
mov [bx].number_s,di ; Кол-во читаемых секторов
mov [bx].b_off,offset buf3
mov dx,cs
mov [bx].b_seg,dx
int 25h ; Каталог в buf3
pop cx
jnc st4 ; Ошибки нет
; Ошибка чтения сектора
lea dx,err_read
mov al,3
call msg
int 20h
st4: ; Определение логического номера сектора первого
; доступного кластера на текущем логическом диске
mov bp,root_s ; Лог.ном.сект.нач.корн.кат.
mov bl,sec_cat
xor bh,bh
add bp,bx ; + сект. в корн. каталоге
mov clu0,bp
mov byte ptr f_flag,0 ; Ищется не файл
; Цикл поиска каталогов вплоть до текущего
st40: mov cx,64 ; Кол. анализируемых записей
lea si,buf3 ; Начало 1 записи каталога
st41: cmp byte ptr [si],0 ; Пустая запись ?
jz st42 ; Пропуск
cmp byte ptr [si],0e5h ; Стертая запись ?
jz st42 ; Пропуск
call comp ; Сравнение с искомым
cmp flag,1 ; Hайден ?
jz st43 ; Найден
st42: add si,32 ; Переход к следующей записи
loop st41
; Ошибка поиска
lea dx,err_read
mov al,4
call msg
int 20h
st43: test byte ptr [di],0ffh ; Конец имени каталога ?
jz st5 ; Нашли !
inc di ; Переход к следующему имени кат.
mov point,di
call read_cat ; Чт.найденного кат. в buf3
jmp st40
st5: call read_cat ; Чт.найденного кат. в buf3
; Поиск защищаемого файла
mov byte ptr f_flag,1 ; Ищется файл
lea ax,fil_name ; Защищаемый файл
mov point,ax
mov cx,64 ; Кол. анализируемых записей
lea si,buf3 ; Начало 1 записи каталога
st51: cmp byte ptr [si],0 ; Пустая запись ?
jz st52 ; Пропуск
cmp byte ptr [si],0e5h ; Стертая запись ?
jz st52 ; Пропуск
call comp ; Сравнение с искомым
cmp flag,1 ; Hайден ?
jz st53 ; Найден
st52: add si,32 ; Переход к следующей записи
loop st51
; Ошибка чтения
lea dx,err_read
mov al,6
call msg
int 20h
st53: mov ax,[si].b_clu
; В АХ начальный кластер этого файла
; Проверка флага инициализации
test f_key,0ffh ; Проверка флага инициализации
jz st54 ; Переход, если инициализации не было
jmp nstart ; Переход на основную программу
; Инициализация
st54: mov key,ax ; Запись начального кластера
mov f_key,1 ; Установка флага инициализации
; Открытие файла
mov ax,3d01h ; Открытие файла для записи
lea dx,fil_name ; Имя файла
int 21h
jnc nst1
; Ошибка чтения
lea dx,err_read
mov al,7
call msg
int 20h
nst1: mov handler,ax
; Установка указателя файла на 3
mov ax,4200h ; Абс. установка от начала
mov bx,handler ; Дескриптор файла
xor cx,cx ; Старшая часть смещения
mov dx,3 ; Младшая часть смещения
int 21h
; Запись в файл
mov ah,40h ; Запись
mov bx,handler ; Дескриптор файла
mov cx,3 ; Количество записываемых байтов
lea dx,key ; Смещение записываемых байтов
int 21h
jnc nst2
; Ошибка чтения
lea dx,err_read
mov al,8
call msg
int 20h
nst2: ; Сообщение основной программы
lea dx,ok
mov al,0
call msg
call kbin ; Ожидание
int 20h
nstart: cmp ax,key ; Сравн. истинного и зап. номеров
jz nst2 ; Все в порядке
; Сообщение основной программы
lea dx,nok
mov al,0
call msg
call kbin ; Ожидание
int 20h
; Чтение подкаталога в buf3
; Вход: SI = начало записи этого подкаталога в вышестоящем каталоге
read_cat proc near
mov bp,clu0
; BP = лог.номер сект.первого доступного кластера
lea bx,buf2 ; BR
mov cl,[bx+11].clus_siz ; Секторов в кластере
xor ch,ch
mov ax,[si].b_clu ; Нач. кластер найд. кат.
sub ax,2 ; Кластеры начинаются с 2
mul cx ; DX:AX нач.сект.найд.кат.отн.конца корн.
add ax,bp
adc dx,0 ; DX:AX лог.нач.сект.найд.кат.
lea bx,b_param ; Блок параметров
mov word ptr [bx].sec_num,ax ; Отн. номер сект.
mov word ptr [bx+2].sec_num,dx ; Отн. номер сект.
mov al,2 ; Диск С
mov cx,-1 ; Признак > 32 M
mov di,num_sec
mov [bx].number_s,di ; Кол-во читаемых секторов
mov [bx].b_off,offset buf3
mov dx,cs
mov [bx].b_seg,dx
int 25h ; Каталог в buf3
pop cx
jnc rc1 ; Ошибки нет
; Ошибка чтения сектора
lea dx,err_read
mov al,5
call msg
int 20h
rc1: ret
read_cat endp
; Сравнение тек. записи каталога с искомой (point)
; При успешном поиске: flag = 1
; SI - нач. найденной записи
comp proc near
mov flag,0 ; Сброс флага поиска
test byte ptr f_flag,0ffh ; Ищется файл ?
jnz comp1 ; Да
test byte ptr [si].f_attr,10h ; Подкаталог ?
jnz comp1 ; Подкаталог
ret ; Выход, если не подкаталог
comp1: mov bp,si ; Нач. тек. имени в каталоге
mov di,point ; Указ. тек. кат.
push cx
mov cx,11
comp2: mov al,byte ptr [di] ; Симв. тек. кат.
cmp al,'.' ; Разделитель ?
jnz comp3 ; Не разделитель
inc di
jmp comp2 ; Пропуск разделительной точки
comp3: cmp al,'\' ; Конец имени ?
jz comp31 ; Конец
cmp al,0 ; Конец всего ?
jnz comp4 ; Не конец
; Имя каталога совпало (имя короче 11 симв.)
comp31: mov flag,1 ; Взведение флага поиска
pop cx
ret ; Выход при успешном поиске
comp4: cmp byte ptr cs:[bp],20h ; Пробел ?
jnz comp5 ; Не пробел
inc bp
dec cx
jmp comp4 ; Пропуск пробела
comp5: cmp al,cs:[bp]
jz comp6 ; Символы совпали
; Символы не совпали
pop cx
ret ; Выход при несовпадении имен
comp6: inc di ; Адрес в тек. каталоге
inc bp ; Адрес в тек. записи каталога
loop comp2
; Имя каталога совпало (имя 11 симв.)
mov flag,1 ; Взведение флага поиска
pop cx
ret ; Выход при успешном поиске
comp endp
; Печать каталога
pri_cat proc near
mov cx,64 ; Кол. выводимых записей
lea si,buf3 ; Начало 1 записи каталога
pri_cat1: cmp byte ptr [si],0 ; Пустая запись ?
jz pri_cat2 ; Пропуск
cmp byte ptr [si],0e5h ; Стертая запись ?
jz pri_cat2 ; Пропустить печать
call c_file ; Печать строки
pri_cat2: add si,32 ; Переход к следующей записи
loop pri_cat1
ret
pri_cat endp
c_file proc near
call wk
pusha
; Печать имени файла
push si
mov cx,11
c_fil1: mov al,[si]
call print
inc si
loop c_fil1
call sp4
; Печать начального кластера
pop si
mov ax,[si].b_clu
call prax
call sp4
; Печать размера файла
mov ax,word ptr [si+2].f_size
call prax
mov ax,word ptr [si].f_size
call prax
popa
ret
c_file endp
; Вывод строки
msg proc near
push ax
mov ah,9
int 21h
pop ax
or al,al
jnz msg1
ret
msg1: call prali
ret
msg endp
; Ввод с клавиатуры
kbin proc near
mov ah,0 ; Функция 0
int 16h ; клавиатурного прерывания
ret
kbin endp
; Печать 16 HEX байтов из [SI]
hex proc near
pusha
mov cx,16
hex1: mov dl,[si]
call pral
call space ; Печать пробела
inc si
loop hex1
call wk ; Перевод строки, возврат каретки
popa
ret
hex endp
; Печать АХ и ВК
praxi proc near
pusha
call prax
call wk
popa
ret
praxi endp
; Печать AL и ВК
prali proc near
pusha
call pral
call wk
popa
ret
prali endp
; Печать четырехзначного шестнадцатеричного числа из AX
prax proc near
push bx
push cx
push ax
and ax,0f000h
mov cl,12
shr ax,cl
call prss
pop ax
push ax
and ax,0f00h
mov cl,8
shr ax,cl
call prss
pop ax
push ax
and ax,0f0h
mov cl,4
shr ax,cl
call prss
pop ax
push ax
and ax,0fh
call prss
pop ax
pop cx
pop bx
ret
prax endp
; Печать двухзначного шестнадцатеричного числа из AL
pral proc near
pusha
push ax
mov cl,4
shr al,cl
call prss
pop ax
call prss
popa
ret
pral endp
; Перевод строки, возврат каретки
wk proc near
mov al,0dh ; Код возврата каретки
call print ; Печать 1 ASCII символа
mov al,0ah ; Код перевода строки
jmp print ; Печать 1 ASCII символа
wk endp
; Печать пробела
space proc near
mov al,32 ; Код пробела
jmp print ; Печать 1 ASCII символа
space endp
; Печать 4 пробелов
sp4 proc near
call space
call space
call space
jmp space
sp4 endp
; Печать одного hex символа из мл. тетр. al
prss proc near
and al,0fh
add al,30h
cmp al,39h
jle print
add al,7
; Печать 1 ASCII символа
print proc near
pusha
mov bx,0fh
mov ah,0eh
int 10h
popa
ret
print endp
prss endp
Code ENDS
END Start
ГЛАВА 3.