имеется загрузчик, полностью рабочий
Код:
use16
org 7C00h
start:
cli
xor ax, ax ;настройка сегментных регистров
mov ds, ax
mov es, ax
mov ss, ax
mov [device], dl
mov sp, 7C00h ;установка sp на начало кода (т.к. стек растет вниз, код не затрется)
mov ax, 0B800h
mov fs, ax ;fs направим на область текстовой видео-памяти
sti
mov ax, 3
int 10h ;установка видеомоды + очистка экрана
mov ah, 1
mov ch, 20h
int 10h
call MenuItem1 ;рисуем меню
GetKey:
xor ax, ax
int 16h ; ждем нажатие клавиши
cmp al, 0Dh
je option ;если Enter, то выбираем с чего грузить
cmp ah, 48h ;вверх
je up
cmp ah, 50h ;вниз
je down
jmp short GetKey
option:
cmp [MenuItem], 0 ;первый пункт меню, грузим с диска С:\
jne StartOS
mov si, load_C ;перемещаем кусок кода на адрес 8000h
mov di, 8000h
mov cx, end_C-load_C
cld
rep movsb
jmp 8000h
up:
cmp [MenuItem], 0 ;перерисовываем пункты
je GetKey
call MenuItem1
jmp short GetKey
down:
cmp [MenuItem], 1
je GetKey
call MenuItem2
jmp short GetKey
MenuItem1:
mov [MenuItem], 0 ;первый пункт активен (белый текст красный фон)
xor dx, dx
mov cx, 18
mov bx, 4Fh
mov bp, load1
mov ax, 1301h
int 10h
mov bp, load2
mov cx, 23
mov dx, 0100h ;второй не активен (белый по черному)
mov bx, 0fh
int 10h
ret
MenuItem2:
mov [MenuItem], 1 ;первый не активен
xor dx, dx
mov cx, 18
mov bx, 0Fh
mov bp, load1
mov ax, 1301h
int 10h
mov bp, load2 ;второй активен
mov cx, 23
mov dx, 0100h
mov bx, 4fh
int 10h
ret
load_C:
mov ax, 3 ;очистка экрана
int 10h
mov ax, 0201h
mov dx, 80h
mov cx, 1
mov bx, 7c00h
int 13h ;грузим MBR в адрес 7C00h
push es
push 7C00h
retf ;и передаем ему бразды правления
end_C:
StartOS:
mov ax, 3 ;очистка экрана
int 10h
pushd 16 ;сектор который нужно прочитать
push 0F00h ;сегмент в который будет произведено чтение
call ReadSector ;читаем первичный сектор
mov eax, [0F000h+0A6h] ;сохраним размер корневого каталога
mov [RootSize], eax
pushd [RootSize]
pushd [0f000h+158]
push 0F00h
call ReadFile ;читаем корневой каталог
mov di, file1
xor ax, ax
SearchFile:
mov si, 0F000h ;адрес где лежит корневой каталог
cmp byte [di], 0 ;если все файлы загружены
je exit ;то грузим ядро
call WriteLoadFile ;иначе выводим имя файла, которое собрались загружать
@@:
xor cx, cx
cmp byte [si], 0 ;если больше нет записей в каталоге
je FileNotFound ;то файл не найден
mov cl, [si+32] ;длинна имени файла в каталоге
cmp cl, byte [di] ;сравниваем с длинной
jne FindNext ;если не равны, то берем следующую запись каталога
push di ;сохраним начало записи и файловой структуры
push si
add di, 3 ;настроим si и di на первые байты имени файла
add si, 33
rep cmpsb ;сравнение
pop si ;восстановим si di
pop di
jne FindNext ;если не тот файл, то ищем дальше
pushd [si+10] ;размер файла
pushd [si+2] ;адрес экстента
mov bx, [di+1]
push word [di+1] ;сегмент в который нужно читать файл
call ReadFile
call OK ;выводим сообщение об успешной загрузке файла
mov al, [di]
xor ah, ah ;следующая файловая структура
add di, ax
add di, 4
;xor ax, ax
;int 16h
;push word [di+1] ;сегмент
;call debug
jmp short SearchFile
FindNext:
mov al, [si] ;длинная текущей записи
xor ah, ah
add si, ax ;следующая запись в каталоге
jmp short @b
FileNotFound:
push 0400h
push 12
push [x]
push error
call WriteString ;вывод сообщения что файл не найден
exit:
push [kernel_seg]
push 0
retf
OK:
push 0E00h
push 12
push [x]
push ok
call WriteString
inc [x]
ret
ReadFile:
push bp
mov bp, sp
mov ecx, [bp+10] ;размер корневого каталога
add ecx, 7FFh ;непонятные мне махинации
shr ecx, 11
mov dx, [bp+4] ;сегмент
mov eax, [bp+6] ;начальный сектор
.NextSector:
push eax
push dx
call ReadSector
add dx, 80h
loop .NextSector
mov sp, bp
pop bp
ret 6
ReadSector:
push bp
mov bp, sp
push ax dx si
mov ax, [bp+4] ;формируем пакет для EDD
mov [DataSeg], ax ;сегмент
mov eax, [bp+6]
mov [LBAlow], eax ;сетора в формате LBA
mov ah, 42h
mov si, Packet ;адрес пакета
mov dl, [device] ;номер привода с которого грузится загрузчик
int 13h
jc .error ;если произошла ошибка то скажем об этом и зависнем
pop si dx ax
mov sp, bp
pop bp
ret 6
.error:
push 0fh
push 0
push 0
push ErrorMsg
call WriteString
jmp $
WriteLoadFile:
push di
add di, 3
push 0a00h
push 0
push [x]
push di
call WriteString ;вывод имени загружаемого файла
pop di
ret
WriteString:
push bp
mov bp, sp
pusha
mov ax, [bp+6] ;строка
mov bx, 160
mul bx
mov di, ax
mov ax, [bp+8]
shl ax, 1 ;колонка
add di, ax
mov si, [bp+4] ;адрес строки
push es
push fs
pop es ;es на сегмент видео-памяти ;будем писать в самое начало
mov ax, [bp+10] ;аттрибуты символов
@@:
lodsb
or al, al ;пока не встретим нуль
je @f
stosw ;пишем символы в видео-память
jmp @b
@@:
pop es
popa
mov sp, bp
pop bp
ret 8
debug:
push bp
mov bp, sp
push ds
mov ds, [bp+4] ;сегмент, которые подвергается дампу
pusha
mov cx, 8
xor di, di
xor si, si
.a1:
push cx
mov cx, 16
push di
.a2:
lodsb
call byte2hex
add di, 6
loop .a2
pop di
add di, 160
pop cx
loop .a1
popa
pop ds
mov sp, bp
pop bp
ret 2
byte2hex:
pusha
push ax
shr al, 4
cmp al, 9
ja @1
or al, 30h
jmp write1
@1:
add al, 'A'-10
write1:
mov ah, 0Fh
mov word [fs:di], ax
pop ax
add di, 2
and al, 0fh
cmp al, 9
ja @2
or al, 30h
jmp write2
@2:
add al, 'A'-10
write2:
mov ah, 0Fh
mov word [fs:di], ax
popa
ret
word2hex:
pusha
xchg al, ah
call byte2hex
add di, 4
xchg al, ah
call byte2hex
popa
ret
dword2hex:
push eax
push eax
shr eax, 16
call word2hex
add di, 8
pop eax
and eax, 0ffffh
call word2hex
pop eax
ret
align 4 ;выравнивание на адрес кратный четырем
Packet:
db 0x10 ; размер пакета
db 0x00
dw 0x0001 ; число читаемых секторов
dw 0x0000 ; смещение
DataSeg dw 0x0000 ;сегмент данных
LBAlow dd 0x00000000 ;сектор в формате LBA
dd 0x00000000
ErrorMsg db 'Error read table ways.', 0
load1 db 'Load from harddisk'
load2 db 'Starting Fatal_Error OS'
ok db 'LOADED', 0
error db 'ERROR', 0
device db ?
file1 db 10 ;длинна имени файла
kernel_seg dw 100h ;сегмент, в который нужно грузить файл
name1 db 'KERNEL.BIN', 0 ;и собственно имя.
file2 db 9
segment2 dw 200h
name2 db 'CDROM.BIN', 0 ;эти файлы вообще ничего в себе не содержат. гуржу, дабы проверить работоспособность
file3 db 10
segment3 dw 500h
name3 db 'DVDROM.BIN', 0
file4 db 0
RootSize dd ?
MenuItem db 0
и ядро
Код:
include 'constants.inc'
org 1000h
start:
mov ax,3
int 10h
mov ah, 1
mov ch, 20h
int 10h
in al,92h
or al,2
out 92h,al
lgdt fword [GDTR]
cli
in al,70h
or al,80h
out 70h,al
mov eax,cr0
or al,1
mov cr0,eax
jmp fword CODE_SELEKTOR:PROTECTED_MODE_ENTRY_POINT
align 8
include 'GDT.inc'
use32
PROTECTED_MODE_ENTRY_POINT:
mov ax, DATA_SELEKTOR
mov ds, ax
mov ss, ax
mov ax, VIDEO_SELEKTOR
mov es, ax
mov esp, STACK_BASE_ADDRESS
cld
PM_CODE:
include 'PM_CODE.asm'
PM_CODE_END:
таблица GDT
Код:
GDT:
NULL_descr db 8 dup(0)
CODE_descr db 0FFh,0FFh,00h,00h,10h,10011010b,11001111b,00h
DATA_descr db 0FFh,0FFh,00h,00h,10h,10010010b,11001111b,00h
GDT_SIZE = $-GDT
label GDTR fword
dw GDT_SIZE-1
dd GDT
так вот. загрузчик успешно загружает мое ядро, в отладчике bochs'а я дохожу до команды jmp fword CODE_SELEKTOR:PROTECTED_MODE_ENTRY_POINT и тут все... осуществляется прижок в никуда... идет команда add [eax], какое-то_число и лезет исключение... бочс перезагружается... само ядро рабочее, я пробовал грузить его через флоппик - результат удовлетворительный. а с сидюка бред... я понимаю, что код читать трудоемко и долго, но все же надеюсь на вашу помощь