Whats wrong with linear address 0x600 ( 0x60:0x00 )

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Whats wrong with linear address 0x600 ( 0x60:0x00 )

Post by muisei »

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.
slasher
Posts: 17
Joined: Sun Oct 24, 2004 11:00 pm
Contact:

Post by slasher »

It is not where you are loading it but a reference from within your code.

Are you sure there isn't anything in the code that assumes you are at address 0x10000 (0x1000:0x00)?

Show us the code and we can help you better.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

My main OS and my MiniDos project are loaded to 600h, so its not the address thats the problem.
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Post by muisei »

This is my MBR written in NASM:

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
And here is a simple kernel:

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
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'.
MNemo
Posts: 5
Joined: Sat Oct 07, 2006 3:03 pm
Location: Germany

Post by MNemo »

if you use

Code: Select all

jmp     0x0060:0x0000           
you can't say

Code: Select all

[ORG 0x600] 
either

Code: Select all

jmp 0x0000:0x0600 ; and

[org 0x0600]
or

Code: Select all

jmp 0x0060:0x0000 ; and

[org 0x0000]
I know my English is bad. So any corrections concerning language won't offend me.
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Post by muisei »

I changed the 'jmp start' to this 'jmp 0x600:0x05'.It still crashed when I load a segment register.
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Post by muisei »

Changed the MBR to load the kernel to 0x1000:0x0000 (0x10000 linear address) , GDT code segment base address and the [ORG 0x600] directive and now everything works fine.

I'm confused.
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Post by muisei »

I figured it out!The problem was the [ORG] directive and the base address in the GDTR.
Post Reply