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