OSDev http://osdev.su/ |
|
переход в PM http://osdev.su/viewtopic.php?f=6&t=751 |
Страница 1 из 2 |
Автор: | Fatal_Error [ 23 май 2013, 21:27 ] |
Заголовок сообщения: | переход в PM |
имеется загрузчик, полностью рабочий Код: 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], какое-то_число и лезет исключение... бочс перезагружается... само ядро рабочее, я пробовал грузить его через флоппик - результат удовлетворительный. а с сидюка бред... я понимаю, что код читать трудоемко и долго, но все же надеюсь на вашу помощь |
Автор: | Himik [ 23 май 2013, 22:13 ] |
Заголовок сообщения: | Re: переход в PM |
А как ты записываешь на CD, в формате дискеты? |
Автор: | 418ImATeapot [ 23 май 2013, 22:18 ] |
Заголовок сообщения: | Re: переход в PM |
Покажи GDT. |
Автор: | ilya [ 24 май 2013, 04:47 ] |
Заголовок сообщения: | Re: переход в PM |
lgdt, впринципе, должна выглядить так "lgdt fword [cs:GDTR]" нету настройки cs:ip в загрузчике, или есть? |
Автор: | Fatal_Error [ 24 май 2013, 05:53 ] |
Заголовок сообщения: | Re: переход в PM |
Цитата: Покажи GDT. есть, чуть ниже кода ядра Himik писал(а): А как ты записываешь на CD, в формате дискеты? через ультра исо. файл-новый-загрузочный СД. Цитата: lgdt, впринципе, должна выглядить так "lgdt fword [cs:GDTR]" нету настройки cs:ip в загрузчике, или есть? они в загрузчике первыми строками идут. вобщем упрощу задачу: я пробовал в таблицу GDT записать одну переменную, и потом считать ее - рузультат удовлетворительный. следовательно, все данные присутствуют в оперативе, чтение с сидюка прошло успешно. еще одна странность: так все норм: Код: include 'constants.inc' org 1000h start: mov ax,3 int 10h mov ah, 1 mov ch, 20h int 10h push 0 push l retf l: jmp PROTECTED_MODE_ENTRY_POINT mov ax, cs mov ax, ds 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 CODE_SELEKTOR:PROTECTED_MODE_ENTRY_POINT 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: align 8 include 'GDT.inc' use32 но без защищенного режима. а вот так нет: Код: include 'constants.inc' org 1000h start: mov ax,3 int 10h mov ah, 1 mov ch, 20h int 10h push 0 push l retf l: mov ax, cs mov ax, ds 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 CODE_SELEKTOR:PROTECTED_MODE_ENTRY_POINT 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: align 8 include 'GDT.inc' use32 если надо могу скинуть образ. |
Автор: | achesnokov [ 24 май 2013, 10:57 ] |
Заголовок сообщения: | Re: переход в PM |
У вас регистр ds неверно присваивается. Вместо mov ax, ds судя по-всему должно быть наоборот. Во-вторых, процессор не умеет одним прыжком переходить сразу в 32-битный режим. Сначала нужно сделать jmp с 16-битным смещением, потом следом уже с 32-битным. Примерно как в поправленном варианте ниже. Код: mov ax, cs mov ds, ax 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 0x8:OFFSET16_ENTRY_POINT OFFSET16_ENTRY_POINT: use32 jmp 0x8:PROTECTED_MODE_ENTRY_POINT PROTECTED_MODE_ENTRY_POINT: |
Автор: | pavia [ 24 май 2013, 12:22 ] |
Заголовок сообщения: | Re: переход в PM |
Всё он умеет. Советую вам разобрать что да как происходит и в чём разница. |
Автор: | ilya [ 24 май 2013, 13:04 ] |
Заголовок сообщения: | Re: переход в PM |
Fatal_Error писал(а): вобщем упрощу задачу: я пробовал в таблицу GDT записать одну переменную, и потом считать ее - рузультат удовлетворительный. следовательно, все данные присутствуют в оперативе, чтение с сидюка прошло успешно. этот тест работать не будет если вы делаете это во время исполнения програмы и если какието проблемы с сег. регистрами.Не надо записывать, надо только считать и сравнить с без использования дополнительной памяти |
Автор: | achesnokov [ 24 май 2013, 14:26 ] |
Заголовок сообщения: | Re: переход в PM |
pavia писал(а): Всё он умеет. Советую вам разобрать что да как происходит и в чём разница. Возможно... В таком случае советую дать какой-нибудь дельный совет коллеге с проблемами, если вы уж так быстры на советы. Я лишь хотел сказать что первый jmp после mov cr0,eax должен быть с 16-битным аргументом в качестве смещения. 32 битные смещения могут использоваться только после первого jmp. |
Автор: | Himik [ 24 май 2013, 16:06 ] |
Заголовок сообщения: | Re: переход в PM |
achesnokov писал(а): Во-вторых, процессор не умеет одним прыжком переходить сразу в 32-битный режим. Сначала нужно сделать jmp с 16-битным смещением, потом следом уже с 32-битным. Если используется префикс 32-битного сегмента, то и смещение может быть 32-битным. Только надо правильно закодировать инструкцию перехода, добавив префикс 32-битного адреса. Думаю, что-то типа jmp fword ... Я использовал такой метод pushd SelCS32 pushd OffsetEntryPoint32 retfd Это код 16-битного сегмента для перехода на 32-битный. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |