Создаем загрузочный диск.
CodingДанные в секторе 1 дорожки 0 головки 0 дисковода 0 для первого откликнувшегося диска (дискеты или твердого диска) загружаются по абсолютному адресу 0000:7c00, и управление передается по этому адресу. Если опрос всех дисков неудачен, управление передается на прерывание INT 18H .
На твердом диске, этот код в "корневом секторе" в действительности определяет активный раздел диска, а затем загружает и выполняет корневой сектор для этого раздела. Это передает управление активной операционной системе диска.
Наша задача - написать процедуру, работающую с адреса CS:07C00h и производящую загрузку OS.
Для простоты предположим, что ядро ОС - первый файл (не фрагментированный) не дискете, с размером 64kb (или меньше). (Первый файл на дискете(1.44) находится в сектре 33.)
Все-бы бало ни чего, если-бы была процедура чтения сектора (типа int 25h), ну вроде и все, больше ни каких проблем загрузка из boot'а вызвать не должна.
IDEAL
MODEL tiny
DATASEG
KernelSeg EQU 01000h
CODESEG
ORG 100h
Start: jmp Start1
ORG 07C00h
Данные из boot сектора грузятся по адрессу 0000:7C00, следовательно мы должны писать под этот адрес.
Start1: jmp Begin
; EB 3C 90
; Таблица для совместимости с DOS
nop
OEMName DB 29h,63h,7Eh,26h,49h,49h,48h,43h
SectSize DW 00200h
ClustSize DB 001h
ResSecs DW 00001h
FatCnt DB 002h
RootSiz DW 000E0h
TotSecs DW 00B40h
Media DB 0F0h
FatSize DW 00009h
TrkSecs DW 00012h
HeadCnt DW 00002h
HidnSec DW 00000h
Данные о дискете, для совместимости с DOS
; Мои переменные
AbsSectNum DW 0
AbsHeadNum DW 0
Begin: ; Рамка
; Читаем ядро
mov ax,KernelSEG
mov es,ax
mov di,100h ; Entry Point - KernelSEG:100h
mov dx,33 ; Первый сектор с данными
; (128 секторов ядра)
nextsect: push dx es di
call ReadSect
pop di es dx
add di,512
inc dx
cmp dx,160
jne nextsect
call far KernelSEG:0100h
; ReadKey
int 20h
; Чтение сектора (DX=номер сектора) ##########################################
Чтение сектора без DOS довольно запаристо: Зная абсолютный номер сектора, нам надо его преобразовать в номер головки, дорожки и сектора.
; ES:DI - куда читать
PROC ReadSect
push di es
; Начало расчета сектора/дорожки/головки
push cs
pop ds
mov cx,[TrkSecs]
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] ; -5-4-3-2-1-0-9-8-7-6-5-4-3-2-1-0-
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
END Start
Подписывайтесь на канал и делитесь им с друзьями