Код (Text): ;--------------------------------------------------------------- ;Сектор 1 ;--------------------------------------------------------------- use16 org 0x7C00 jmp 0x0000:main nop main: xor ax,ax ;ds=0 mov ds,ax mov si,load_msg ;вывод сообщения call print_str xor ax,ax mov es,ax ;буфер для считывания es:bx=0x0000:0x7E00 mov bx,0x7E00 mov dl,0 ; номер устройства = 0 mov dh,0 ; головка = 0 mov ch,0 ; трек = 0 mov cl,2 ; сектор = 2 mov al,1 ; считать секторов = 1 mov ah,2 int 0x13 jc read_error ; в случае ошибки процедуре read_error передать управление xor ax,ax mov ds,ax ;ds=0 jmp 0x0000:0x7E00 ; прыжок на считанный сектор ;--------------------------------------------------------------- ;Процедуры ;--------------------------------------------------------------- print_str: mov ah,0x0E mov bh,0x00 mov bl,0x07 .nextchar: lodsb ; вывод сообщения or al,al jz .return int 0x10 jmp .nextchar .return: ret read_error: mov si,error_msg call print_str jmp $ ret ;--------------------------------------------------------------- ;Данные ;--------------------------------------------------------------- load_msg db 'Loading Kernel...',13,10,0 error_msg db 'Error',13,10,0 ;--------------------------------------------------------------- times 510-($-$$) db 0 ; дополняем до 510 байт dw 0xAA55 ; последние два байта AA и 55 ;--------------------------------------------------------------- ;Сектор 2 ;--------------------------------------------------------------- sector2: mov si,kernel_msg call print_str ; вывод сообщения о удачно считанном ядре hlt ;--------------------------------------------------------------- ;Данные ;--------------------------------------------------------------- kernel_msg db 'Loaded Kernel.',13,10,0 ;--------------------------------------------------------------- Ребята помогите пожалуйста !Борюсь с этой проблемой не первую неделю ни как не выходит.Прочитал наши и забугорные форумы , посмотрел примеры таких загрузчиков и всеровно не работает.Выводит первое сообщение нормально , а второе о считанном ядре ни в какую.Тестирую всё на Qemu.Отладчик gdb не показывает после считавания наличия CF , значит считалось вроде как нормально .В чем же проблема?
Код вроде правильный (единственно, вместо hlt в конце лучше ставить jmp $ либо cli/hlt, потому что при просто hlt после первого же прерывания процессор "проглотит" hlt и управление получит мусор, находящийся в памяти). Каким образом он записывается на дискету? P.S. Проверил под Bochs - работает.
По умолчанию фасм делает образ дискеты(вот этот код я так вставляю в фасм и компилирую) , я его монтирую в qemu и делаю бут с него.Я исправил в конце на jmp $ - не помогло.Может я в qemu что то не так делаю(( qemu.exe -L . -m 128 -hda win.img -soundhw all -localtime -M pc -s -fda boot.bin
Действительно в Bochs все работает!Спасибо за помощь!Товарищи , кто знает от чего возникает такая проблема в Qemu отпишитесь пожалуйста
Видимо, qemu очень не нравится, когда образ дискеты обрывается на середине сектора - сектор он не читает, хотя и ошибки не выдаёт. Если в конец исходника добавить "times 0x8000-$ db 0", то и под qemu всё нормально.
Diamond, еще раз спасибо.Вот поизучал статьи те..Опять проблемка..хотя вроде как говорится всё по инструкции делал. Теперь загрузчик выглядит так: Код (Text): ;--------------------------------------------------------------- ;Сектор 1 ;--------------------------------------------------------------- use16 org 0x7C00 jmp 0x0000:main nop main: xor ax,ax ;ds=0 mov ds,ax mov si,load_msg ;вывод сообщения call print_str mov ax,0x2000 mov es,ax ;буфер для считывания es:bx=0x2000:0x0000 mov bx,0x0000 mov dl,0 ; номер устройства = 0 mov dh,0 ; головка = 0 mov ch,0 ; трек = 0 mov cl,2 ; сектор = 2 mov al,9 ; считать секторов = 9 mov ah,2 int 0x13 jc read_error ; в случае ошибки процедуре read_error передать управление xor ax,ax mov ds,ax ;ds=0 jmp 0x2000:0x0000 ; прыжок на считанный сектор ;--------------------------------------------------------------- ;Процедуры ;--------------------------------------------------------------- print_str: mov ah,0x0E mov bh,0x00 mov bl,0x07 .nextchar: lodsb ; вывод сообщения or al,al jz .return int 0x10 jmp .nextchar .return: ret read_error: mov si,error_msg call print_str jmp $ ret ;--------------------------------------------------------------- ;Данные ;--------------------------------------------------------------- load_msg db 'Loading Kernel...',13,10,0 error_msg db 'Error',13,10,0 ;--------------------------------------------------------------- times 510-($-$$) db 0 ; дополняем до 510 байт dw 0xAA55 ; последние два байта AA и 55 ;--------------------------------------------------------------- ;Сектор 2 ;--------------------------------------------------------------- file 'kernel.bin' kernel.bin - размер 4,01 кб (значит надо считать более 8 секторов) kernel.bin собирался из трех файлов startup.c kernel.c procs.c Код startup.c: Код (Text): void _start(){ kernel_main(); } Код procs.c : Код (Text): #define video_width 80 //øèðèíà ýêðàíà #define video_height 25 //âûñîòà ýêðàíà #define video_ram 0xB8000 //àäðåñ âèäåîïàìÿòè void clear(){ int i; char *video = video_ram; for (i = 0; i < (video_width*video_height) ; i++){ *(video + i*2)=' '; } } Код kernel.c : Код (Text): void kernel_main(){ clear(); for(;;); } Cобирал gcc kernel.bin так: gcc -ffreestanding -c -o procs.o procs.c gcc -ffreestanding -c -o startup.o startup.c gcc -ffreestanding -c -o kernel.o kernel.c ld -Ttext 0x200000 -o kernel.bin startup.o procs.o kernel.o objcopy kernel.bin -O binary В итоге на этапе загрузки всё встает.В чем проблема.В сегменте(при джампе)?или же в самой сборке образа?
gcc генерирует 32-битный код, рассчитанный на плоскую модель памяти. На начальной стадии загрузки, в том числе в момент начала исполнения бутсектора, процессор работает в 16-битном реальном режиме. Так что напрямую загружать gcc'шный код нельзя, а нужно сначала выполнить настройку окружения. Пример кода можно взять, например, тут: http://lowlevel.ru/?namespace=osdev8
а стек настраивать разве ненужно? мой старый кодес...работает Код (Text): ;!------------------------------------------------------------------------------------------------------------- ; ; getting started inject code ; ;% my incs ;include 'equals.inc' b_p equ byte ; 8 w_p equ word ; 16 d_w_p equ dword ; 32 p_w_p equ pword ; 48 q_w_p equ qword ; 64 t_w_p equ tword ; 80 dq_w_p equ dqword ; 128 BootStart = 7c00h use16 org BootStart cli mov w_p [cs:BootStart-02h], 0 mov w_p [cs:BootStart-04h], ss mov ss, w_p [cs:BootStart-02h] mov w_p [cs:BootStart-02h], sp mov sp, BootStart-04h push es push ds pushad push cs pop ds dec w_p [cs:0413h] mov ax, w_p [cs:0413h] shl ax, 6 ; *1024/16 mov es, ax mov si, CodeStart xor di, di mov cx, 512/4 cld rep movsd push es push 0 retf CodeStart: org 0 ;% indicator mov ax, 0b800h mov es, ax mov w_p [es:0], 'GG' xor ax, ax int 16h mov ax, 201h mov cx, 1 mov dx, 80h mov di, 0 mov es, di mov bx, BootStart int 13h ;% hook int13 and trap mov eax, d_w_p [ds:01h*04h] mov d_w_p [cs:MY_INT_01.Old_01], eax mov ax, cs shl eax, 10h mov ax, MY_INT_01 mov d_w_p [ds:01h*04h], eax mov eax, d_w_p [ds:13h*04h] mov d_w_p [cs:MY_INT_13.Old_13], eax mov ax, cs shl eax, 10h mov ax, MY_INT_13 mov d_w_p [ds:13h*04h], eax ;% go boot popad pop ds pop es cli mov ss, w_p [cs:BootStart-04h] mov sp, w_p [cs:BootStart-02h] db 0eah dw BootStart dw 0 ;!------------------------------------------------------------------------------------------------------------- ; ; Int13h handler ; ; MY_INT_13: cmp ah, 02h ; sectors read? je .SectorsRead cmp ah, 42h ; extended read? je .SectorsRead pushf call d_w_p [cs:.Old_13] pushfd push bp mov bp,sp or w_p [ss:bp+02h], 100h ; set tf flag pop bp popfd retf 02h ;% back to mama =) db 0eah .Old_13: dd 0 .SectorsRead: pushf call d_w_p [cs:.Old_13] pushfd push bp mov bp,sp or w_p [ss:bp+02h], 100h ; set tf flag pop bp popfd retf 02h ;!------------------------------------------------------------------------------------------------------------- ; ; Int01h handler ; ; MY_INT_01: push si push ds push bp mov bp, sp mov si, w_p [ss:bp+6h] mov ds, w_p [ss:bp+8h] pop bp cmp w_p [ds:si], 010fh ; lgdt? jne .NoLgdt mov ax, 0b800h mov es, ax mov di, 0 mov ah, 4 mov cx, 32 .PutCodeString: lodsb mov dl, al mov bh, 0 mov bl, al shr bl, 4 and bl, 00001111b add bx, HexTable mov al, [cs:bx] stosw mov bh, 0 mov bl, dl and bl, 00001111b add bx, HexTable mov al, [cs:bx] stosw mov al, 20h stosw loop .PutCodeString .EternalPause: nop jmp .EternalPause .NoLgdt: pop ds pop si push bp mov bp,sp or w_p [ss:bp+06h], 100h ; set tf flag pop bp iret ;% back to mama =) db 0eah .Old_01: dd 0 HexTable: db '0123456789ABCDEF' align 200h
Спасибо.Значит без защищенного ни как не обайдусь))Буду его грызть))Собирал или линковал значит я правильно?Тоесть если бы я хотел адрес загрузки 0x7E00 , то прописал бы при линковке ld -Ttext 0x7E0000 -o kernel.bin startup.o procs.o kernel.o
vorobei99 советую прочитать про скриптовый язык LD Код (Text): # kernel.ld ENTRY(start) SECTIONS { .text 0x7E00 : AT(0) { start = . ; *(.text) ; } } Код (Text): # ld -T kernel.ld --oformat binary startup.o kernel.o -o kernel.bin
Честно сколько не пробывал не вышло.Да и какое там окружение надо.На том сайте они делают под защищенный режим.Я хочу просто под реальный режим ..Попробовал как ты диамонд сказал и райзер.Такое впечатление , что он не может найти точку входа в процедуру _start.Если кому не трудно можете сделать так чтобы это всё грузилось и скинуть ,что по пунктам делали.А то делая ,как в статье что-то не выходит.Я использую Fasm и Dev-Cpp(Gcc и LD)