CodeNet / Языки программирования / Ассемблер / Пишем "многозадачную" ОС в "Real Mode"
CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
Модуль disk.asm
; Чтение сектора (DX=номер сектора) ##########################################
; ES:DI - куда читать
PROC ReadSect
push di es
; Начало расчета сектора/дорожки/головки
push cs
pop ds
mov cx,18
mov si,dx
; tmp=(Sect/Sectors);
mov ax,si
xor dx,dx
div cx
mov di,ax
; Sec=Sect-(tmp*Sectors)+1;
mov ax,di
imul cx
mov dx,si
sub dx,ax
inc dx
mov [AbsSectNum],dx
; Hea=tmp & 1;
mov ax,di
and ax,1
mov [AbsHeadNum],ax
; Trk=(Sect-(Hea*Sectors)-(Sec-1))/(Sectors*2);
imul cx
push ax
mov ax,si
pop dx
sub ax,dx
mov dx,[AbsSectNum]
dec dx
sub ax,dx
mov dx,cx
shl dx,1
push ax
push dx
xor dx,dx
pop bx
pop ax
div bx ; AX = AbsTrackNum
; Конец расчетов
mov cx,ax
mov al,cl
shr cx,2
and cl,0C0h
mov ch,al
and cx,0FFC0h
mov ax,[AbsSectNum] ; г5T4T3T2T1T0T9T8T7T6T5T4T3T2T1T0¬
or cl,al ; CX = c c c c c c c c C c S s s s s s
pop es bx ; ES:BX = Куда считывать
mov dx,[AbsHeadNum]
mov dh,dl ; Номер головки
mov dl,0 ; Номер диска 0 = A
mov al,1 ; Количество считываемых секторов
mov ah,2 ; Номер функции
int 13h
ret
ENDP ReadSect
; Чтение сектора в стандартный буффер ########################################
RSSData DW 0
PROC CachedReadSector
cmp dx,[cs:RSSData]
je RSSEnd
mov [cs:RSSData],dx
push di si es ax bx cx dx
lea di,[sector]
push cs
pop es
call ReadSect
pop dx cx bx ax es si di
RSSEnd: ret
ENDP CachedReadSector
; Чтение FAT'а ###############################################################
PROC ReadFAT
push cs
pop es
mov dx,1
lea di,[FAT]
readfat1: push es dx di
Call ReadSect
pop di dx es
add di,512
inc dx
cmp dx,10
jne readfat1
ret
ENDP ReadFAT
; Выдает следующий сектор после DX (через FAT) ###############################
gns_flag DW 0
PROC GetNextSector
cmp dx,2
je gns03
cmp [Word Ptr cs:gns_flag],0
jne gns04
push cx di bx
lea di,[FAT]
mov ax,dx
mov bx,ax
mov cx,3
mul cx
shr ax,1
add di,ax
mov dx,[di]
and bx,1
je gns01 ; Если номер кластера четный
shr dx,4
jmp gns02
gns01: and dx,0FFFh
gns02: pop bx di cx
ret
gns03: mov dx,[RootSect]
ret
gns04: mov [Word Ptr cs:gns_flag],0
add dx,33-2
ret
ENDP GetNextSector
; Конвертит номер сектора в номер кластера ###################################
Sect2ClustRoot DW 0
PROC Sect2Clust
cmp dx,33
jb Sect2Clust1
sub dx,33-2
mov [Word Ptr cs:Sect2ClustRoot],0
ret
Sect2Clust1: mov [Word Ptr cs:Sect2ClustRoot],1
ret
ENDP Sect2Clust
; По строке (обычно командной) выдает номер сектора (DS:DI = строка ) ########
; Возвращает AX = номер превого сектора каталога
GetSectorName DB 13 DUP (0),0
GetSectorClust DW 0
Prohod DW 0
PROC GetSectorNum
call UpperString ; [DI] = D:\CAT1\CAT2\
mov al,[di] ; AL = Диск 'A'-'Z'
sub al,'A' ; AL = Диск 0 - 32
xor ax,ax
mov [Word Ptr cs:GetSectorClust],2
mov [Word Ptr cs:gns_flag],1
mov [cs:Prohod],ax
add di,3 ; [DI] = CAT1\CAT2\
nextsubdir: mov si,di
gsn003: mov al,[si]
or al,al
je gsn001
cmp al,'\'
je gsn001
inc si
jmp gsn003
gsn001: cmp di,si ; [DI] = CAT1\CAT2
je gsn002 ; [SI] = \CAT2
xor cx,cx
mov bx,si
push si
lea si,[GetSectorName]
gsn005: mov al,[di]
cmp al,'.' ; Если есть расширение
je gsn004
mov [cs:si],al
inc di
inc si
inc cx
cmp di,bx
jne gsn005
pop di
; Добьем имя нулями
gsn006: mov [Byte Ptr cs:si],20h
inc cx
inc si
cmp cx,11
jne gsn006
jmp gsn007
gsn002: mov ax,[cs:Prohod]
or ax,ax
jne gsn0021
mov ax,[Root] ; Корень
jmp gsn0022
gsn0021: mov ax,[GetSectorClust]
gsn0022: ret
gsn004: cmp cx,8
je gsn008
mov [Byte Ptr cs:si],20h
inc cx
inc si
jmp gsn004
gsn008: inc di
inc cx
cmp cx,12
je gsn010
mov al,[di]
or al,al
je gsn009
mov [cs:si],al
inc si
jmp gsn008
gsn009: pop di
jmp gsn006
gsn010: pop dx
gsn007: push di
; Ищем в корне запрошеный каталог (CAT1)
mov dx,[GetSectorClust]
lea di,[sector]
gsn13: call GetNextSector
cmp dx,0FFFh
je gsn14
push dx
call CachedReadSector
mov [Word Ptr cs:gns_flag],0
lea di,[sector]
lea si,[GetSectorName]
mov cx,16 ; 16 - количество записей в одном секторе
gsn12: push di si cx
call CmpStrings
pop cx si di
jc gsn11
notdir: add di,32
dec cx
jne gsn12
pop dx
jmp gsn13
gsn14: pop di ; Не найдено не фига
xor ax,ax
ret
gsn11: ; Найдена запись - сравним аттрибуты
mov al,[di+11]
and al,10h
je notdir ; Это не каталог
mov ax,[di+01Ah]
mov [GetSectorClust],ax
pop dx di
inc di
mov [Word cs:Prohod],1
mov [Word Ptr cs:gns_flag],1
jmp nextsubdir
ENDP GetSectorNum
; FindFirst ##################################################################
; Возвращает: AX=0=Ok; AX=1=Patch not found
PROC FindFirst
; Читаем FAT
push cs
pop ds
; Узнаем номер сектора, где начинается корень
lea di,[dos_CurDir]
call GetSectorNum ; В AX - номер кластера с каталогом
or ax,ax
je ff03
mov dx,ax
mov [Word Ptr cs:gns_flag],1
push cs
pop es
call GetNextSector
ff02: push dx
call CachedReadSector
pop dx
; Копируем первую запись в каталоге в структуру _dos
lea si,[sector]
mov cx,16
ff01: mov al,[si]
or al,al ; 0 - пустая запись каталога
je nofile
cmp al,'х' ; 'x' - удаленая запись
je nofile
mov ax,[si+11]
cmp ax,0Fh ; Если это LFN
je nofile
lea di,[dos_FileName]
mov bx,cx
mov cx,32
rep movsb
jmp ff_makefind
nofile: add si,32
dec cx
or cx,cx
jne ff01
cmp dx,32
jna nofile1
call GetNextSector
jmp ff02
nofile1: inc dx
jmp ff02
ff_makefind: ; Копируем содержимое структуры dos_ в структуру _find
lea si,[dos_FileName]
lea di,[find_FileName]
mov cx,32
rep movsb
mov ax,16
sub ax,bx
mov [di],dx
mov [di+2],ax
xor ax,ax
ret
ff03: mov ax,1
ret
ENDP FindFirst
; Ищет следующий файл в каталоге #############################################
; Возвращает: AX=0=Ok; AX=1=Patch not found
PROC FindNext
lea si,[find_FileName]
mov dx,[si+32] ; DX - номер сектора
mov ax,[si+34]
fnNextSector0: cmp ax,15 ; Надо читать следующий
je fnNextSector1
mov [Word Ptr cs:gns_flag],1
fnNextSector: push cs
pop es
push ax
call Sect2Clust ; DX - номер кластера
cmp [Word Ptr cs:Sect2ClustRoot],0
jne fnNextSector5 ; Если корень
call GetNextSector
cmp dx,0FFFh
je fnNextSector2
fnNextSector4: push dx
call CachedReadSector
pop dx ax ; Нужный сектор считан
inc ax ; AX - номер записи (0..15)
push ax
shl ax,5 ; AX=AX*5
lea si,[sector]
add si,ax
; Проверим на пустую запись, удаление и LFN
mov bl,[si]
or bl,bl ; 0 - пустая запись каталога
je fn_nofile
cmp bl,'х' ; 'x' - удаленая запись
je fn_nofile
mov bx,[si+11]
cmp bx,0Fh ; Если это LFN
je fn_nofile
lea di,[dos_FileName]
mov cx,32
rep movsb
pop ax
lea si,[dos_FileName]
lea di,[find_FileName]
mov cx,32
rep movsb
mov [di],dx
mov [di+2],ax
xor ax,ax
ret
fn_nofile: pop ax
jmp fnNextSector0
fnNextSector2: pop ax
mov ax,1
ret
fnNextSector1: xor ax,ax
dec ax
jmp fnNextSector
fnNextSector5: cmp [Word Ptr cs:gns_flag],1
je fnNextSector51
inc dx
cmp dx,33
je fnNextSector2
fnNextSector51: mov [Word Ptr cs:gns_flag],0
jmp fnNextSector4
ENDP FindNext
Оставить комментарий
Оставлять комментарии могут только зарегистрированные пользователи.
Если вы не являетесь зарегистрированным пользователем, то вам необходимо зарегистрироваться. Регистрация бесплатна. Если вы уже зарегистрированы на CodeNet, то вам необходимо ввести логин и пароль в верхней (Alt-U) части страницы.
