flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Review my loader...

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 21 Oct 2009, 19:03
Hello
Might you have a peek at my booter and kernel code?
I pieced it together from ideas i learned on the net.
It loads 16 sectors from disk and executes the code.
I am not a pro at this stuff so i would like some intervention.
I am mostly concerned about the entry and exit points
and also about the segment and stack setup...
Any comments or constructive criticism are greatly appreciated.

Booter:
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Booter code.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

use16

        jmp     0x07C0:BooterEntry ; Portability hack.

BooterEntry:

        ; Setup segments and stack.

        cli
        mov     ax,cs
        mov     ds,ax
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax
        mov     sp,0xFFFF
        sti

        ; Store boot drive passed from BIOS.

        mov     [g_BootDriveNumber],dl
        add     dl,'A'
        mov     [g_BootDriveLetter],dl

        ; Print that the booter is running.

        mov     si,g_BootingMessage
        mov     cx,c_BootingMessage_size
        call    PrintBuffer

        ; Print that we are about to start loading.

        mov     si,g_LoadingSectorsMessage
        mov     cx,c_LoadingSectorsMessage_size
        call    PrintBuffer

        ; Setup to start loading sectors.

        mov     [g_SectorsToLoad],16 ; We want to load 16 sectors.
        mov     [g_LoadSectorTries],c_MaxLoadSectorTries ; Try n times before giving up.

        mov     [g_CurrentSector],2 ; Start from 2nd sector (1st=boot)
        mov     [g_CurrentSegment],c_ImageLoadSegment ; ES:BX

        ; Reset the disk drive system.

ResetDrive:

        ; Let us know if the drive is being reset.

        mov     si,g_ResetDriveMessage
        mov     cx,c_ResetDriveMessage_size
        call    PrintBuffer

        ; Reset the disk drive via BIOS.

        xor     ax,ax ; BIOS reset disk function.
        int     0x13  ; Reset controller before loading.

        ; Load one sector from disk.

LoadSector:

        ; Setup destination for sector.

        mov     ax,word[g_CurrentSegment]
        mov     es,ax
        xor     bx,bx

        ; Setup location of source sector.

        mov     dl,[g_BootDriveNumber]   ; Drive number.
        mov     dh,0                     ; Head number.
        mov     cl,byte[g_CurrentSector] ; Sector number
        mov     ch,0                     ; Track number

        ; Read in one sector via BIOS

        mov     ah,0x02 ; BIOS read sectors function.
        mov     al,1    ; Read one sector.
        int     0x13    ; Invoke BIOS disk service.
        jnc     SectorLoaded ; If ok - continue

        ; We reach this point when sector reading fails.

        dec     [g_LoadSectorTries] ; Decrement the retry counter.
        jnz     ResetDrive          ; Try again only if retry counter is greater than zero.

        ; If we reach this point, the sector loader has failed the max number of times.

        mov     si,g_ImageLoadErrorMessage
        mov     cx,c_ImageLoadErrorMessage_size
        call    PrintBuffer

        jmp     $ ; Hang it up.

        ; We reach this point when a sector has been loaded.

SectorLoaded:

        ; Print that a sector has been loaded.

        mov     si,g_LoadedSectorMessage
        mov     cx,c_LoadedSectorMessage_size
        call    PrintBuffer

        ; Adjust the variables and see if any more sector to load.

        dec     [g_SectorsToLoad] ; One sector less to do.
        jz      ImageLoaded       ; If sectors count is equal to zero we are done loading.

        mov     [g_LoadSectorTries],c_MaxLoadSectorTries ; Reset retry counter.
        inc     [g_CurrentSector]     ; Increment sector index.
        add     [g_CurrentSegment],32 ; adding 20h(32 dec) to segment register equals
                                      ; to adding 512 to bx register
        jmp     LoadSector            ; loop until all sector are loaded

        ; We reach this point when all sectors have been loaded.

ImageLoaded:

        ; Print that the image was loaded
        ; and we are about to execute it.

        mov     si,g_ImageLoadedMessage
        mov     cx,c_ImageLoadedMessage_size
        call    PrintBuffer

        ; Jump far into the loaded code.

        jmp      c_ImageLoadSegment:0x0000


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PrintBuffer
;
; Input: DS:SI -> buffer
;        CX = size
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PrintBuffer:
        pusha
        mov     ah,0x0E   ; BIOS TeleType function.
        mov     bx,0x0007 ; BH = page number 0, BL = color attribute WHITE
PrintBufferLoop:
        lodsb
        int     0x10 ; Invoke BIOS video service.
        loop    PrintBufferLoop
        popa
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Booter data.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

c_ImageLoadSegment = 0x0050

g_BootDriveNumber db 0
g_LoadSectorTries db 0
c_MaxLoadSectorTries = 8
g_SectorsToLoad   dw 0
g_CurrentSector   dw 0
g_CurrentSegment  dw 0

g_BootingMessage  db 'Booted from drive ('
g_BootDriveLetter db '?)',13,10
c_BootingMessage_size = $ - g_BootingMessage

g_LoadingSectorsMessage db 'Loading 16 sectors.',13,10
c_LoadingSectorsMessage_size = $ - g_LoadingSectorsMessage

g_ResetDriveMessage db 'Resetting drive system.',13,10
c_ResetDriveMessage_size = $ - g_ResetDriveMessage

g_LoadedSectorMessage db 'One sector loaded.',13,10
c_LoadedSectorMessage_size = $ - g_LoadedSectorMessage

g_ImageLoadedMessage db 'Image loaded, executing...',13,10
c_ImageLoadedMessage_size = $ - g_ImageLoadedMessage

g_ImageLoadErrorMessage db 'Failed to load image.',13,10
c_ImageLoadErrorMessage_size = $ - g_ImageLoadErrorMessage

times 510-($-$$) db 0 ; Padd out to 510 bytes.
dw 0xAA55 ; Add boot signature.

    

Kernel:
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Kernel code.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

use16
        ; Setup segments and stack.

        cli
        mov     ax,cs
        mov     ds,ax
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax
        mov     sp,512*16 ; Top of image.
        sti

        ; Print that the kernel is loaded.

        mov     si,g_KernelEntryMessage
        mov     cx,c_KernelEntryMessage_size
        call    PrintBuffer

        ; Eat some space in the code.

        jmp     SkipFakeCode
        times 512*8 db 0 ; 8 sectors of fake code.
    SkipFakeCode:

        ; Print that we are deep into the kernel.

        mov     si,g_KernelDeepMessage
        mov     cx,c_KernelDeepMessage_size
        call    PrintBuffer

        ; Print that we are going to hang.

        mov     si,g_KernelHangMessage
        mov     cx,c_KernelHangMessage_size
        call    PrintBuffer

        jmp     $ ; Hang it up.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PrintBuffer
;
; Input: DS:SI -> buffer
;        CX = size
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PrintBuffer:
        pusha
        mov     ah,0x0E   ; BIOS TeleType function.
        mov     bx,0x0007 ; BH = page number 0, BL = color attribute WHITE
PrintBufferCycle:
        lodsb
        int     0x10 ; Invoke BIOS video service.
        loop    PrintBufferCycle
        popa
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Kernel data.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

g_KernelEntryMessage db 'Kernel entry point ok.',13,10
c_KernelEntryMessage_size = $ - g_KernelEntryMessage

g_KernelDeepMessage db 'Deep into the kernel.',13,10
c_KernelDeepMessage_size = $ - g_KernelDeepMessage

g_KernelHangMessage db 'Hanging the kernel...',13,10
c_KernelHangMessage_size = $ - g_KernelHangMessage

times 512*16-($-$$) db 0 ; Padd out to 16 sectors.

    

I used PARTCOPY to write on floppy drive A.
Code:
PARTCOPY.EXE BOOTER.BIN 0 200 -f0 0
PARTCOPY.EXE KERNEL.BIN 0 2000 -f0 200
    

I tested in Bochs emulator and it works Smile

Edit:

This was the memory map i found here to work from.
I think i should max out the kernels SP to 0xFFFF so if the kernel
code was big enough it would not get trashed by the stack pointer.
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 16-Bit Memory Map.
;
; 0x0000:0x0000 - 0x0040:0x0000 -> Interrupt Vector Table.
; 0x0040:0x0000 - 0x0050:0x0000 -> Bios Communication Area.
; 0x0050:0x0000 - 0x9000:0xFFFF -> Image loading segment. (kernel code)
; 0x07C0:0x0000 - 0x07C0:0x0200 -> Booter code. (Also equal to 0000:7C00 - 0000:7E00)
; 0xA000:0x0000 - 0xFFFF:0x0010 -> Video, Option roms, BIOS...
; 0xA000:0x0000 - 0xA000:0xFFFF -> Video memory in graphical mode.
; 0xB800:0x0000 - 0xB800:0xFFFF -> Video memory in text mode.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 21 Oct 2009, 19:03
View user's profile Send private message Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 22 Oct 2009, 00:29
Just being picky but, honestly i'd suggest writing a hlt loop instead. Something else to point out, you're initializing everything twice, once in the kernel and in the boot loader. This isn't a real big problem though. Only certain things need to be initialized (for instance, not all the segment registers are a problem on most machines). Are you planning on sticking with real mode or are you planning on going into pmode? I forget if it affects 16bit stuff or not, but you might want to consider looking into the A20 gate. It's something quite silly that could get in your way later on.
Post 22 Oct 2009, 00:29
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 22 Oct 2009, 03:47
Yeah, I just figured out how to get it into pmode today Smile
I had to tweak my GDT a bit to get the RM/PM segments to agree.
And yes, i will enable the a20, i want a big 'ol 4gb in flat land.
I did setup everything twice so it was clear what is on both ends.
Once room starts to get tight i will chop the extra stuff out.
First to make it work, then to make it work better.
Post 22 Oct 2009, 03:47
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20300
Location: In your JS exploiting you and your system
revolution 22 Oct 2009, 04:38
bitshifter wrote:
First to make it work, then to make it work better.
That is an excellent philosophy. Best comment I've seen on this board for a while.
Post 22 Oct 2009, 04:38
View user's profile Send private message Visit poster's website Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 22 Oct 2009, 11:52
Chances are, you won't have to worry about room getting tight unless you're going into vesa or something and are storing images or waveforms in your kernel. Though if you want another bit of criticism, the RM/PM segment agreement is really only good for making the interrupts work. However, if you're using 32bit stuff, you'll run into problems because the bios stuff will only be able to work with addresses under 0xFFFF, unless you find a way to tweek them using the gdt and some more fancy stuff. Though really, depending on what you plan on doing, you may just as easily write your own routines instead of using the bios routines. Usually it's safe to do a bunch of setting things up (video mode, loading kernel, etc) before jumping into pmode and then simply coding basic input and output routines and then doing all the hardware drivers that you'd inevitably have to do anyway (usb, mouse, etc).
Post 22 Oct 2009, 11:52
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 22 Oct 2009, 12:23
I used descriptors for null,linear32,code32,data32,code16,data16.
Now i can simply select a descriptor and switch between modes.
The GDT is tweaked at runtime to adjust the addressing spaces.

I am now writing a VGA driver first so i can make a debugger Smile
Then a keyboard driver would be the next thing to do.
And then i need to make a very simple file system for it.
My goal is to make a 32bit game engine operating system.
Post 22 Oct 2009, 12:23
View user's profile Send private message Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 22 Oct 2009, 13:06
I'm going to warn you ahead of time that it's not going to be nearly as easy as you may expect it to be... IMO, VGA and VESA are slow for most games. I get flicker just clearing my screen all at once (then again, my resolution is very high and i'm using string functions for copying memory, but still). You may want to consider compatibility with or conversion of linux modules if you want anything super fast, ESPECIALLY if you're considering 3d.
Post 22 Oct 2009, 13:06
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 22 Oct 2009, 20:18
Initially im going to use my mode-x library.
I have the 3D part mostly all roughed out already.
Ultimately i would like to have an 82845G driver.

Edit:

This is what i came up with to get into little 32bit mode...
I can be used with my previous booter code in this thread.
This is my first time being in protected mode all by myself...
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 16-Bit (Real Mode) Kernel Entry Point.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

use16

        ; Eat some code to show we loaded multiple sectors.

        jmp     .AfterFakeCode
        times 512*8 db 0 ; 8 sectors of fake code.
    .AfterFakeCode:

        ; Disable any interruptions.

        cli

        ; Setup a data segment so we can access our data.

        mov     ax,cs
        mov     ds,ax

        ; Adjust the GDT and apply it.

        shl     ax,4 ; DS * 16 = Linear address of segment base.
        mov     bp,ax ; Put it in the pointer register.
        lea     dx,[gdt+bp] ; Get physical address of GDT.
        mov     [gdt_TableHeader+2],dx
        mov     [gdt_CodeDescriptor+2],ax
        mov     [gdt_DataDescriptor+2],ax
        shr     ax,16 ; Linear address / (2^16=65536)
        mov     [gdt_CodeDescriptor+4],al
        mov     [gdt_DataDescriptor+4],al
        mov     [gdt_CodeDescriptor+7],ah
        mov     [gdt_DataDescriptor+7],ah
        lgdt    [gdt_TableHeader]

        ; Set the protected mode bit.

        smsw    ax   ; Store Machine Status Word into AX.
        or      ax,1 ; Set the first bit.
        lmsw    ax   ; Load Machine Status Word from AX.

        ; Jump far into 32-Bit code. (flushes pipeline)

        jmp     gdt_CodeSelector:Enter32BitCode ; CS is then gdt_CodeSelector

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 32-Bit (Protected Mode) Kernel Entry Point.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

use32

Enter32BitCode:

        ; Setup data and stack segments.

        mov     ax,gdt_DataSelector
        mov     ds,ax
        mov     ss,ax

        ; Setup linear destination segment for printing.

        mov     ax,gdt_LinearSelector
        mov     es,ax

        ; Print that we are here in 32-Bit land.

        mov     esi,g_HelloWorldMessage
        mov     ecx,c_HelloWorldMessage_size
        call    PrintBuffer

        ; Enter the main loop.

    MainLoop:

        hlt
        jmp     MainLoop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PrintBuffer
;
; Input: DS:ESI -> Buffer
;        ECX = Size
;
; Assumes ES = Linear base selector of GDT.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PrintBuffer:

        pusha

        ; Get current caret offset.

        mov     ax,0x0F0E
        mov     dx,0x03D4
        out     dx,al
        inc     dx
        in      al,dx
        xchg    ah,al
        dec     dx
        out     dx,al
        inc     dx
        in      al,dx
        movzx   ebx,ax

        ; Set a color attribute.

        mov     ah,0x0F ; White on black.

    .PrintBufferLoop:

        ; Load a byte and process it.

        lodsb
        cmp     al,10 ; Ignore the LINE-FEED character.
        je      .CharacterProcessed
        cmp     al,13 ; Handle the CARRIAGE-RETURN character.
        je      .AdvanceCaretNewLine

        ; Write character and attribute to video memory.

        mov     [es:(ebx*2+0xB8000)],ax

        ; Increase the offset value and continue.
        ; TODO: Add bounds checking here...

        inc     bx
        jmp     .CharacterProcessed

    .AdvanceCaretNewLine:

        ; TODO: Add code here...

    .CharacterProcessed:

        loop    .PrintBufferLoop ; Loop through buffer.

        ; Set new caret offset.

        mov     al,0x0E
        mov     ah,bh
        mov     dx,0x03D4
        out     dx,ax
        inc     ax
        mov     ah,bl
        out     dx,ax

        ; Were outta here.

        popa
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Kernel data.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

gdt:
    dw 0
    dw 0
    db 0
    db 0
    db 0
    db 0
gdt_LinearDescriptor:
gdt_LinearSelector = $ - gdt
    dw 0xFFFF
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_CodeDescriptor:
gdt_CodeSelector = $ - gdt
    dw 0xFFFF
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
gdt_DataDescriptor:
gdt_DataSelector = $ - gdt
    dw 0xFFFF
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_TableHeader:
    dw $ - gdt - 1
    dd gdt

g_HelloWorldMessage db 'Hello from 32-Bit land!'
c_HelloWorldMessage_size = $ - g_HelloWorldMessage

times 512*16-($-$$) db 0 ; Padd out to 16 sectors.
    
Post 22 Oct 2009, 20:18
View user's profile Send private message Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 23 Oct 2009, 09:44
Never make the computer do what can be done by the assembler itself. Since the main site for the project we've been working on is down, i'll just upload a zip release (i'll have to tell wolf when he gets back that the move to mercurial isn't entirely finished yet, since the site for it used to work, but one of his servers could be down too since he's been away for a few weeks). I'll upload it until the site at the end of this link is working right again. You'll find gdt.asm to be really helpful here, but feel free to peek at the rest of it.

I'd give you some more code (a printf-like routine [even called printf, but doesn't comes with all the features]) that i've done on my own for another text mode kernel (also under-developed), but that'd ruin the fun of making your own kernel from scratch.


Description:
Download
Filename: microKernel_src.zip
Filesize: 52.06 KB
Downloaded: 485 Time(s)

Post 23 Oct 2009, 09:44
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 23 Oct 2009, 12:14
Im not sure what you mean?
Maybe to hardcode the GDT?
By doing that i can ditch the setup hack.
Plus i can park it in with all my other data.
This works, but is it correctly implemented?
Note: 0x0050 is the 16-Bit kernel entry segment.
Code:
gdt:
    dw 0
    dw 0
    db 0
    db 0
    db 0
    db 0
gdt_LinearSelector = $ - gdt
    dw 0xFFFF
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_CodeSelector = $ - gdt
    dw 0xFFFF
    dw 0x0050*16
    db 0 ; LOBYTE(0x0050*16/65536)
    db 10011010b
    db 11001111b
    db 0 ; HIBYTE(0x0050*16/65536)
gdt_DataSelector = $ - gdt
    dw 0xFFFF
    dw 0x0050*16
    db 0 ; LOBYTE(0x0050*16/65536)
    db 10010010b
    db 11001111b
    db 0 ; HIBYTE(0x0050*16/65536)
gdt_TableHeader:
    dw $ - gdt - 1
    dd gdt + 0x0050*16    

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 23 Oct 2009, 12:14
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 23 Oct 2009, 16:58
Out of sheer paranoia, the first thing I do is cli and store dl before the sti, in case the BIOS trashes it in an interrupt - so something like this:
Code:
;...
        cli ; <<<

        jmp     0x07C0:BooterEntry ; Portability hack. 

BooterEntry: 

        ; Setup segments and stack. 

        mov     ax,cs 
        mov     ds,ax 
        mov     es,ax 
        mov     fs,ax 
        mov     gs,ax 
        mov     ss,ax 
        mov     sp,0xFFFF 

        ; Store boot drive passed from BIOS. 

        mov     [g_BootDriveNumber],dl 
        add     dl,'A' 
        mov     [g_BootDriveLetter],dl

        sti ; <<<
;...    


If you're looking to add multi- core/processor (or ACPI) you will also want these areas of memory:

Code:
; 0x9FC0:0x0000 - 0x9FC0:0x03FF EBDA
; 0xE000:0x0000 - 0xE000:0xFFFF ROM
    


Hope that helps and it goes well Cool
Post 23 Oct 2009, 16:58
View user's profile Send private message Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 24 Oct 2009, 01:16
Quote:
Im not sure what you mean?
Maybe to hardcode the GDT?
By doing that i can ditch the setup hack.
Plus i can park it in with all my other data.
This works, but is it correctly implemented?


Exactly my point. If it can be hardcoded without loosing functionality of the program, why not hardcode it? It saves the computer lots of time. And it might help yourself to use macros (change them if you want of course) since it's easier to read and manage and it doesn't really change the output at all. It's helpful later because then you can add segments for special data sections you find you end up wanting to constantly manipulate (like you'll notice the code i uploaded likes to keep a segment register reserved for the video lfb).
Post 24 Oct 2009, 01:16
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 24 Oct 2009, 01:24
Thanks for the tips guys Smile
I think i will have an equates file visible by booter and kernel
which defines the kernel entry segment like c_ImageLoadSegment = 0x0050
Then if i ever decide to change my mind i only need to change one value.
I dont have any books besides RBIL and Intel manuals so everything
i learn is either from them or code i see on the net, im kinda shooting from the hip.
Post 24 Oct 2009, 01:24
View user's profile Send private message Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 24 Oct 2009, 01:38
Quote:
I dont have any books besides RBIL and Intel manuals so everything
i learn is either from them or code i see on the net, im kinda shooting from the hip.


welcome to the club =p
Post 24 Oct 2009, 01:38
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4330
Location: Now
edfed 24 Oct 2009, 13:28
what is boring with IA32 is:

the format of GDT entries.
why the help didn't they made it easy to modify like:
Code:
mov dword[GDT+entry+base],base
mov dword[GDT+entry+limit],size
mov dword[GDT+entry+attributes],attributes
mov dword[GDT+entry+pagetable],0 ;if = 0, then, no paging.
    

WHY? Crying or Very sad
Post 24 Oct 2009, 13:28
View user's profile Send private message Visit poster's website Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 24 Oct 2009, 13:47
kohlrak wrote:
Quote:
Im not sure what you mean?
Maybe to hardcode the GDT?
By doing that i can ditch the setup hack.
Plus i can park it in with all my other data.
This works, but is it correctly implemented?


Exactly my point. If it can be hardcoded without loosing functionality of the program, why not hardcode it? It saves the computer lots of time. And it might help yourself to use macros (change them if you want of course) since it's easier to read and manage and it doesn't really change the output at all. It's helpful later because then you can add segments for special data sections you find you end up wanting to constantly manipulate (like you'll notice the code i uploaded likes to keep a segment register reserved for the video lfb).


I disagree, in this case eg: if you hard coded it, you would not be able to say let Dos load your kernel, but if you left it as it was you could use a mz exe as a kernel and just as easy load it from dos from hdd, usb, floppy, cd etc plus your boot loader.

PS: vesa + pmode can be very smalL, i fited vesa high res, pmode, gui, vesa font, cdplayer in less than 512bytes Laughing
Post 24 Oct 2009, 13:47
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20300
Location: In your JS exploiting you and your system
revolution 24 Oct 2009, 13:53
edfed wrote:
WHY? Crying or Very sad
Legacy. The old '286 supports paging. It all started from there and they had to keep it all backwards compatible.
Post 24 Oct 2009, 13:53
View user's profile Send private message Visit poster's website Reply with quote
kohlrak



Joined: 21 Jul 2006
Posts: 1421
Location: Uncle Sam's Pad
kohlrak 24 Oct 2009, 14:36
Quote:
I disagree, in this case eg: if you hard coded it, you would not be able to say let Dos load your kernel, but if you left it as it was you could use a mz exe as a kernel and just as easy load it from dos from hdd, usb, floppy, cd etc plus your boot loader.


If you're going down that route instead of using your own boot loader, even easier to use grub for most people. Razz

Quote:
PS: vesa + pmode can be very smalL, i fited vesa high res, pmode, gui, vesa font, cdplayer in less than 512bytes Laughing


If you read the source i posted, you'd find that your examples (especially the ones on OSDev) were alot of help (commented a few times i think). So i know what you can do (If only we could convince you to write tutorials for most common hardware as clean as your PMode example), but for whatever reason, vesa still feels slow, even if it is small.

Quote:
Legacy. The old '286 supports paging. It all started from there and they had to keep it all backwards compatible.


Wouldn't the smaller size cause problems with the GDTR? It could always, naturally, figure out based on a few flags here and there whether it's 80286 or 80386 or not, but wouldn't that be a problem for the CPU? Better to just scrap and start over... Because seriously, who's going to want to mix entry types like that? If someone throws a 386 entry on a 286 machine, they deserve what they get. I don't see why backwards compatibility would be a problem (since it could assume it's a 286 until it has reason to believe otherwise).
Post 24 Oct 2009, 14:36
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 24 Oct 2009, 14:55
Yeah, i understand that it locks me in at 0x0050 like an MZ.
Im going to hardcode it since it will only use my own bootloader.

Also, i have made my first pmode string printing routine, yay :)
It only took me two days to get it working, pretty sad i might say...
The nice thing is it works in linear space and does wraparound and scrolling.
I tried hardware scrolling but it kept moving the base address on me :(
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PrintString
;
; Input: DS:ESI -> String (NULL Terminated)
;
; Assumes ES = Linear base selector of GDT.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PrintString:

        pusha

        ; Get current caret offset.

        mov     ax,0x0F0E
        mov     dx,0x03D4
        out     dx,al
        inc     dx        ; 0x03D5
        in      al,dx
        xchg    ah,al
        dec     dx        ; 0x03D4
        out     dx,al
        inc     dx        ; 0x03D5
        in      al,dx
        movzx   ebx,ax    ; EBX = Linear offset.

    .PrintLoop:

        ; Load a byte and process it.

        lodsb
        cmp     al,0  ; Terminate upon NULL character.
        je      .Finished
        cmp     al,10 ; Ignore the LINE-FEED character.
        je      .PrintLoop
        cmp     al,13 ; Handle the CARRIAGE-RETURN character.
        je      .NewLine

        ; Write character and attribute to video memory.

        mov     ah,0x0F ; Color attribute. (White on Black)
        mov     [es:(ebx*2+0xB8000)],ax ; Ooh, thats fancy :)

        ; Increase the offset value and continue.

        inc     bx
        cmp     bx,80*25
        jl      .PrintLoop

        ; We can safely fall through into the NewLine handler.
        ; We already know we are out of range and we just want to scroll up.
        ; I guess we could do a jump to just before the (mov bx,80*25-80).

        ; Do a CR/LF and scroll up if needed.

    .NewLine:

        ; x = p % 80
        ; y = p / 80
        ; p = p + (80 - x) Add remaining chars to position to get to next row.

        mov     ax,bx ; Linear caret position.
        mov     cx,80 ; Screen is 80 columns wide.
        xor     dx,dx ; Clear DX for DIV instruction.
        div     cx    ; AX = p / 80, DX = p % 80
        sub     cx,dx ; remaining = 80 - (p % 80)
        add     bx,cx ; p = p + (80 - (p % 80))

        cmp     bx,80*25-80
        jle    .PrintLoop
        mov     bx,80*25-80

        mov     edx,80*2 ; Head starts at x(0), y(1) and tail is behind it at x(0), y(0)
    .ScrollLoop:
        mov     eax,dword[es:(edx+0xB8000)]      ; Read two characters and their attributes from the head.
        mov     dword[es:(edx+0xB8000-80*2)],eax ; Write two characters and their attributes into the tail.
        add     edx,4
        cmp     edx,80*2*25   +80*2 ; This extra (+80*2) pulls in an offscreen line into the last line :S
        jl      .ScrollLoop

        jmp     .PrintLoop

    .Finished:

        ; Set new caret offset.

        mov     al,0x0E
        mov     ah,bh
        mov     dx,0x03D4
        out     dx,ax
        inc     al ; 0x0F
        mov     ah,bl
        out     dx,ax

        ; Were outta here.

        popa
        ret    


Edit:
Ok, now that its up and running i need to think about a file system.
I have read EVERY post in the OS construction area and still need ideas.
After playing with FAT12 i thought it was a bit more than it needed to be.
I am thinking using LFB is the hardest to use but the most efficient...
And maybe i should have some type of header since the block size is
not 512 bytes on all of my floppy drives, some say they are 128 byte blocks.
Boy, since 512 was so common people started using the word blocks
interchangibly with the word sectors, now that will confuse a beginner.
So, what would the simplest and most efficient file system be, is it FAT12?
Post 24 Oct 2009, 14:55
View user's profile Send private message Reply with quote
Alphonso



Joined: 16 Jan 2007
Posts: 295
Alphonso 25 Nov 2009, 12:52
bitshifter wrote:
I think i should max out the kernels SP to 0xFFFF so if the kernel code was big enough it would not get trashed by the stack pointer.
Wouldn't you be better off using 0 for max and alignment? I guess it probably wont make a great deal of difference if your going to fix it up later in your code.
Post 25 Nov 2009, 12:52
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.