Чтобы использовать целочисленную арифметику, умножим 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.

Наши рекомендации