Accord to me, Dex(a guy from the forum) and this tutorial:
http://www.frontiernet.net/~fys/rombios.htm
the addresses from 0x600 to 0x9FBFF are free.So I can load my kernel at the first free byte which is 0x600,right?When I load it at this address the boch's debugger falls into infinite 'CPU_LOOP 1', but when I load it at linear address 0x10000 (0x1000:0x00) everything is OK.
Why is this happening?
By the way I'm working in Real mode.
Whats wrong with linear address 0x600 ( 0x60:0x00 )
This is my MBR written in NASM:
And here is a simple kernel:
Actualy i debuged with boch's builtin debugger and found that the 'gdtr' base address is '0x00'.So I moved '0x00' to the 'DS' register.Now the 'gdtr' base is correct but there is still a problem.After I enter PM an try to load a segment register bochs falls into 'CPU_LOOP 1'.
Code: Select all
[BITS 16]
[ORG 0x00]
jmp 0x07C0:start ;Goto segment 0x07C0
start:
cli
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0xffff
sti
mov ebx,446 ;The begining of the Partition table
mov cx,4 ;4 partition tables.Loop for each
.loop1: ;Loops trough the partition tables
push cx
cmp BYTE [ebx+4],0x00
je .loop1_pass ;If zeroe is found in the partition table then there is no partitiona so pass the itteration
mov edx,0 ;First byte of the os_table
mov cx,(os_table_end-os_table_begin)/8 ;Number of the OSes in the table.Itterate for each
.loop2:
mov al,[os_table_begin+edx] ;Move the first byte of each os_table entry to AL
cmp BYTE [ebx+4],al ;Compare AL to the OS ID in the partition table
je .print_name ;If found a match then Print the name of the os
cmp cx,1 ;If no apropriate entry found then print 'Unknown' partition
je .print_unknown ;If CX>1 the there are more itterations to do before print 'Unknown'
jmp .loop2_end
.print_name:
lea si,[os_table_begin+edx+1] ;Print the selected os name
call DisplayMessage
jmp .out
.print_unknown:
mov si,msgUnknown
call DisplayMessage
jmp .out
.loop2_end:
add edx,8 ;EDX now points to the next entry in os_table
loop .loop2
.out:
cmp BYTE [ebx],0x80 ;If active partition then Print 'Active' at the end
je .print_activ
mov si,msgNL
call DisplayMessage
jmp .loop1_pass
.print_activ:
inc BYTE [active] ;Every time an active pratition is found then increment [active]
;At the end if [active]>1 then an invalid pratition table is foun
mov si,msgActive
call DisplayMessage
mov si,msgNL
call DisplayMessage
mov al,[ebx+1]
mov [hed],al
mov al,[ebx+2]
mov [sec],al
mov al,[ebx+3]
mov [cyl],al
.loop1_pass:
add ebx,16 ;EBX now points to the next entry in the partition table
pop cx
dec cx
jnz .loop1
cmp BYTE [active],1
je read
jb .no_active
mov si,msgTooMany
call DisplayMessage
mov ah,0
int 16h
jmp .end
.no_active:
mov si,msgNoActive
call DisplayMessage
mov ah,0
int 16h
.end:
jmp $
;---------------------------------------;
; Read a sector to the memory ;
;---------------------------------------;
read:
mov ah,0
int 16h
mov dl,0x80
mov dh,[hed]
mov cl,[sec]
mov ch,[cyl]
mov ax,0x0060
mov es,ax
mov bx,0x0000
mov ah,2 ;Load disk datato ES:BX(the number of the function)
mov al,15 ;Load 1 sector.This is the second bootloader(the OS's)
int 13h ;Read!
jc .error
jmp 0x0060:0x0000 ;Jump to the program
.error:
mov si,msgError
call DisplayMessage
jmp read ;If didn't succeed then try to read again
DisplayMessage:
pushad
.repeat:
lodsb ;load next character
or al,al ;test for NUL character
jz .done
mov ah,0x0E ;BIOS teletype
mov bh,0x00 ;display page 0
mov bl,0x07 ;text attribute
int 0x10 ;invoke BIOS
jmp .repeat
.done:
popad
ret
msgNoActive db 0x0D,0x0A,"No active partition",0x0A,0x0D,0x00
msgTooMany db 0x0D,0x0A,"Too many active partitions",0x00
msgError db 0x0D,0x0A,"Error reading from HDD",0x00
msgUnknown db "Unknown",0x00
msgActive db " Active",0x00
msgNL db 0x0D,0x0A,0x00
active db 0
cyl db 0
hed db 0
sec db 0
os_table_begin:
db 250,"BabyOS",0x00
db 7 ,"WinXP ",0x00
db 67, "Linux ",0x00
db 99, "UnixSV",0x00
db 165,"FBSD ",0x00
db 166,"OBSD ",0x00
db 169,"NetBSD",0x00
os_table_end:
times 510-($-$$) DB 0
end dw 0xAA55
Code: Select all
[BITS 16]
[ORG 0x600]
jmp start
start:
cli ; Clear or disable interrupts
mov ax,cs
mov ds,ax
mov es,ax
mov gs,ax
mov fs,ax
mov ss,ax
mov sp,0xffff
lgdt [gdtr] ; Load GDT
mov eax,cr0 ; The lsb of cr0 is the protected mode bit
or al,0x01 ; Set protected mode bit
mov cr0,eax ; Mov modified word to the control register
jmp codesel:go_pm
bits 32
go_pm:
mov ax,datasel
mov ds,ax ; Initialise ds & es to data segment
mov es,ax
mov ss,ax
mov fs,ax
mov ax,videosel ; Initialise gs to video memory
mov gs,ax
sti
mov BYTE [gs:0x0],'Z'
jmp $ ; Loop
gdtr:
dw gdt_end-gdt-1 ; Length of the gdt
dd gdt ; physical address of gdt
gdt:
nullsel equ $-gdt ; $->current location,so nullsel = 0h
gdt0: ; Null descriptor,as per convention gdt0 is 0
dd 0 ; Each gdt entry is 8 bytes, so at 08h it is CS
dd 0
; In all the segment descriptor is 64 bits
codesel equ $-gdt ; This is 8h,ie 2nd descriptor in gdt.Code descriptor 4Gb flat segment at 0000:0000h
dw 0xffff ; Limit 4Gb bits 0-15 of segment descriptor
dw 0x0600 ; Base 0h bits 16-31 of segment descriptor (sd)
db 0x00 ; Base addr of seg 16-23 of 32bit addr,32-39 of sd
db 0x9a ; P,DPL(2),S,TYPE(3),A->Present bit 1,Descriptor
; privilege level 0-3,Segment descriptor 1 ie code
; or data seg descriptor,Type of seg,Accessed bit
db 0xcf ; Upper 4 bits G,D,0,AVL ->1 segment len is page
; granular, 1 default operation size is 32bit seg
; AVL : Available field for user or OS
; Lower nibble bits 16-19 of segment limit
db 0x00 ; Base addr of seg 24-31 of 32bit addr,56-63 of sd
datasel equ $-gdt ; ie 10h, beginning of next 8 bytes for data sd.Data descriptor 4Gb flat seg at 0000:0000h
dw 0x0ffff ; Limit 4Gb
dw 0x0000 ; Base 0000:0000h
db 0x00 ; Descriptor format same as above
db 0x92
db 0xcf
db 0x00
videosel equ $-gdt ; ie 18h,next gdt entry
dw 3999 ; Limit 80*25*2-1
dw 0x8000 ; Base 0xb8000
db 0x0b
db 0x92 ; present,ring 0,data,expand-up,writable
db 0x00 ; byte granularity 16 bit
db 0x00
gdt_end
if you use
you can't say
either
or
Code: Select all
jmp 0x0060:0x0000
Code: Select all
[ORG 0x600]
Code: Select all
jmp 0x0000:0x0600 ; and
[org 0x0600]
Code: Select all
jmp 0x0060:0x0000 ; and
[org 0x0000]
I know my English is bad. So any corrections concerning language won't offend me.