Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

OS

58 views
Skip to first unread message

Yeoj

unread,
Mar 16, 2013, 3:20:24 PM3/16/13
to
I can't figure out why my OS is not booting to the MB mark in memory. I have researched all I can and I am stuck. I am calling an assembly kernel.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Yeoj Bootloader Version 1.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

%define version '1.0'

[BITS 16]
[ORG 0x7C00]


main:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main = whole program
; Move the location into DS
; Move Welcome String
; call Print to execute it
; JMP to Kernel to get there
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cli
mov ax,0x7C00 ; Setup the Data Segment register
; Location of data is DS:Offset
mov ds,ax ; Now I know where I'm at
mov ds, ax
mov fs, ax
mov es, ax
mov gs, ax

mov ax, 0x0000 ; set the stack
mov ss, ax
mov sp, 0xFFFF
mov bp, 0xFFFF
sti

mov si, Welcome ; Load Welcome String

call Print ; jump to the Print

jmp Kernel ; jump to Kernel Set up

;;;;;;;;;;;;;;;;
; Procedures ;
;;;;;;;;;;;;;;;;

Print:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Print = Print Setup
; Set up all of the attributes for printing
; When finished Jumps to Print String
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

mov ah,0x0E ; The function to display a chacter (teletype)
mov bh,0x00 ; Page number 0 in this case
mov bl,0x04 ; Red text attribute?
jmp PrintStr ; Jumps to PrintStr

PrintStr:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PrintStr = Print String
; Set up the registers for the interrupt call
; Will write until it finds a null character
; When Null is found then JMP to Printed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

lodsb ; LOaD String Block [SI] into AL and increases SI by one
or al,al ; looks for al = 0 for temination
jz Done ; Jump and stop the printing
int 0x10 ; Call the BIOS video interrupt
jmp PrintStr ; Loop back round to the top

Done:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Done = Finished Printing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ret ;Done


Kernel:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Kernel = Set up for the Kernel
;Sets up A20, GDT, IDT
;jumps to Kernel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

A20:
;;;;;;;
; A20 ;
;;;;;;;

mov ax,0x2401 ;enable A20
int 15
cmp ax,0x86 ; Checks for Campatablity
je Fail
mov si, A20Load ; Bring in A20 Text
Call Print
jmp GDT


;;;;;;;;;;;;;;;
; GDT and IDT ;
;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Global Descriptor Table (GDT) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

gdt:
dw 0,0,0,0 ; Null

dw 0x07FF ; 8Mb - limit=2047
dw 0x0000 ; base address=0
dw 0x9A00 ; code read/exec
dw 0x00C0 ; granularity=4096, 386

.data:
dw 0x07FF ; 8Mb - limit=2047
dw 0x0000 ; base address=0
dw 0x9200 ; data read/write
dw 0x00C0 ; granularity=4096, 386

idt_48:
dw 0 ; idt limit=0
dw 0,0 ; idt base=0L

gdt_48:
dw 0x800 ; gdt limit=2048, 256 GDT entries
dw gdt,0x0 ; gdt base = 0x0xxx
GDT:
cli
lgdt[gdt_48] ;
sti
mov si, GDTLoad ; Bring in GDT Text
call Print ; Print it


mov ax, 0 ;
int 0x16 ;Wait for Keystroke to Load Kernel

mov si, dotall
Call Print

xor ax, ax
add ax, 1 ; Clear Carry Bit

mov si, DAPS ; Load DAPS Struct to SI
mov ah, 0x42 ; Read Functions
mov dl, 0x80 ; Active Boot Drive
int 0x13

jc Fail ; If something goes wrong...

gotoPMoDe:
cli

mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x1000:0x0 ; Jump to Kernel

Fail:
mov si, Failure
Call Print
jmp $

;;;;;;;;;;;;;;;;
; Data ;
;;;;;;;;;;;;;;;;

Welcome db 'YOS',13,10,version,13,10,'',13,10,'Boot-Successful',13,10,0 ; Data Red Dwarf Version and Boot Success
GDTLoad db 'GDT Loading ...',13,10,0 ; GDT Message
A20Load db 'A20 Loading ...',13,10,0 ; A20 Message
PMDLoad db 'PMD Loading ...',13,10,0 ; PMD Message
dotall db '.',13,10,0
Failure db 'Failure',13,10,0
;;;;;;;;;;;;;;;;;;
; Jump To Kernel ;
;;;;;;;;;;;;;;;;;;

;;;;;;;;
; DAPS ;
;;;;;;;;

DAPS: db 0x10 ; Size of Structure (16 bytes)
db 0 ; Always 0
db 1 ; Number of Sectors to Read (1x512)
db 0 ; Always 0
dd 0x10000 ; Target Location for Reading To
dw 0 ; Page Table (0, Disabled)
dd 1 ; Read from Second Block
dd 0 ; Large LBAs, ignore

;;;;;;;;;;;;;;;;;
; Fill and Sign ;
;;;;;;;;;;;;;;;;;

times 510-($-$$) db 0 ; Fill the rest with zeros
dw 0xAA55 ; Boot loader signature

Rod Pemberton

unread,
Mar 16, 2013, 9:34:08 PM3/16/13
to
"Yeoj" <joeyt...@gmail.com> wrote in message
news:a3d89b1a-ef8d-4df6...@googlegroups.com...
> I can't figure out why my OS is not booting to the MB mark
> in memory. I have researched all I can and I am stuck.
> I am calling an assembly kernel.
>

Ok.

> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ; Yeoj Bootloader Version 1.0
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> %define version '1.0'
>
> [BITS 16]
> [ORG 0x7C00]
>

Ok.

The brackets aren't needed. You might also want a "SECTION .text"
etc.

>
> main:
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ; main = whole program
> ; Move the location into DS
> ; Move Welcome String
> ; call Print to execute it
> ; JMP to Kernel to get there
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> cli
> mov ax,0x7C00 ; Setup the Data Segment register
> ; Location of data is DS:Offset
> mov ds,ax ; Now I know where I'm at
> mov ds, ax
> mov fs, ax
> mov es, ax
> mov gs, ax
>

You've set all the segments to 0x7C00. You probably wanted
0x07C0. The segment is multiplied by 16 or shifted 4 bits then
added to the offset in real mode (RM), i.e., CS<<4+IP or CS*16+IP.

Correcting that still might not do what you want. Most BIOSes set
CS=0x0 and IP=0x7C00. If yours does that, then your code will
work with your BIOS. However, some BIOSes some set CS=0x07C0 and
IP=0x0. Your code might need to be adjusted to work for both
combinations of CS and IP. Actually, it probably needs to be
rewritten for any combination of values that satisfy CS<<4+IP or
CS*16+IP. You might want to set CS explicitly via a far jump to
the following instruction.

> mov ax, 0x0000 ; set the stack
> mov ss, ax
> mov sp, 0xFFFF
> mov bp, 0xFFFF
> sti

SP and BP likely need to be word aligned (two bytes), i.e.,
0xFFFE. POP instructions increment SP, so if you have a POP
before any PUSHes to the stack then SP will overflow or wrap to
0x0 where your BIOS IDT is... You might want a smaller value for
SP and BP, e.g., 0x7C00 or 0x7000 or 0x600 etc.
I can't confirm if the print routine works by reading it.

> Kernel:
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;Kernel = Set up for the Kernel
> ;Sets up A20, GDT, IDT
> ;jumps to Kernel
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> A20:
> ;;;;;;;
> ; A20 ;
> ;;;;;;;
>
> mov ax,0x2401 ;enable A20
> int 15
> cmp ax,0x86 ; Checks for Campatablity
> je Fail
> mov si, A20Load ; Bring in A20 Text

This may be a problem. BIOS support for enabling A20 is erratic
and problematic . There are two common alternate methods:
keyboard controller A20 method and the PS/2 A20 method. PS/2
method works on most modern machines. Some older machines require
keyboard controller method. There are a number of pages on the
alt.os.development FAQ website managed by James Harris discussing
various A20 issues. You can find other pages on A20 via Google or
Yahoo, or on the OSDev.org forums, or I can provide more links if
needed. The last link below shows a sampling of the BIOS support
of the A20 functions.

http://aodfaq.wikispaces.com/a20
http://aodfaq.wikispaces.com/mc-a20-timing
http://aodfaq.wikispaces.com/boot
http://aodfaq.wikispaces.com/machine+characteristics


> Call Print
> jmp GDT
>
>
> ;;;;;;;;;;;;;;;
> ; GDT and IDT ;
> ;;;;;;;;;;;;;;;
>
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ; Global Descriptor Table (GDT) ;
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> gdt:
> dw 0,0,0,0 ; Null
>
> dw 0x07FF ; 8Mb - limit=2047

Most people set this to 0xFFFF for either 1MB or 4GB.

> dw 0x0000 ; base address=0
> dw 0x9A00 ; code read/exec
> dw 0x00C0 ; granularity=4096, 386
>

Most people use CF instead of C0.

> .data:
> dw 0x07FF ; 8Mb - limit=2047

Most people set this to 0xFFFF for either 1MB or 4GB.

> dw 0x0000 ; base address=0
> dw 0x9200 ; data read/write
> dw 0x00C0 ; granularity=4096, 386
>

Most people use CF instead of C0.

> idt_48:
> dw 0 ; idt limit=0
> dw 0,0 ; idt base=0L
>
> gdt_48:
> dw 0x800 ; gdt limit=2048, 256 GDT entries
> dw gdt,0x0 ; gdt base = 0x0xxx

Isn't gdt_48 supposed to be 8 bytes?

Usually, most people set two labels "gdt" and "gdt_end" around the
GDT entries, then they subtract to get the entries for gdt_48.

gdt_48:
dw gdt_end - gdt - 1
dd 0
dw 0

The two zero's comprise the physical address of the gdt. They're
unset. Most code computes the address of the gdt label and fills
in the physical address in gdt_48 before issuing an LGDT
instruction. I don't see that in your code below ...

> GDT:
> cli
> lgdt[gdt_48] ;
> sti
> mov si, GDTLoad ; Bring in GDT Text
> call Print ; Print it
>

There might be a problem here. See comment above.

> mov ax, 0 ;
> int 0x16 ;Wait for Keystroke to Load Kernel
>
> mov si, dotall
> Call Print
>
> xor ax, ax
> add ax, 1 ; Clear Carry Bit
>
> mov si, DAPS ; Load DAPS Struct to SI
> mov ah, 0x42 ; Read Functions
> mov dl, 0x80 ; Active Boot Drive
> int 0x13
>
> jc Fail ; If something goes wrong...
>
> gotoPMoDe:
> cli
>

I can't confirm if this routine works by reading it.

> mov eax, cr0
> or eax, 1
> mov cr0, eax
>

Ok.

> jmp 0x1000:0x0 ; Jump to Kernel
>

That'll work if you know your code is at 0x10000 (64KB). For 1MB,
you probably want 0xFFF0 instead of 0x1000. Usually, a RETF or a
JMP FAR is used, instead of absolute segment:offset values.
They're used because the value to jump to can be computed and
saved in memory for a JMP FAR or pushed onto the stack for a RETF.

> Fail:
> mov si, Failure
> Call Print
> jmp $
>
> ;;;;;;;;;;;;;;;;
> ; Data ;
> ;;;;;;;;;;;;;;;;
>
> Welcome db
> 'YOS',13,10,version,13,10,'',13,10,'Boot-Successful',13,10,0 ;
> Data Red Dwarf Version and Boot Success
> GDTLoad db 'GDT Loading ...',13,10,0 ; GDT Message
> A20Load db 'A20 Loading ...',13,10,0 ; A20 Message
> PMDLoad db 'PMD Loading ...',13,10,0 ; PMD Message
> dotall db '.',13,10,0
> Failure db 'Failure',13,10,0
> ;;;;;;;;;;;;;;;;;;
> ; Jump To Kernel ;
> ;;;;;;;;;;;;;;;;;;
>

Ok.

> ;;;;;;;;
> ; DAPS ;
> ;;;;;;;;
>
> DAPS: db 0x10 ; Size of Structure (16 bytes)
> db 0 ; Always 0
> db 1 ; Number of Sectors to Read (1x512)
> db 0 ; Always 0
> dd 0x10000 ; Target Location for Reading To
> dw 0 ; Page Table (0, Disabled)
> dd 1 ; Read from Second Block
> dd 0 ; Large LBAs, ignore
>
> ;;;;;;;;;;;;;;;;;
> ; Fill and Sign ;
> ;;;;;;;;;;;;;;;;;
>

I'm not familiar with this.

> times 510-($-$$) db 0 ; Fill the rest with zeros
> dw 0xAA55 ; Boot loader signature

Ok.


Rod Pemberton




Rod Pemberton

unread,
Mar 16, 2013, 9:49:19 PM3/16/13
to
"Rod Pemberton" <do_no...@notemailnotq.cpm> wrote in message
news:ki36e8$6eu$1...@speranza.aioe.org...
> "Yeoj" <joeyt...@gmail.com> wrote in message
> news:a3d89b1a-ef8d-4df6...@googlegroups.com...

[SNIP]

(correction)

> That'll work if you know your code is at 0x10000 (64KB). For
> 1MB, you probably want 0xFFF0 instead of 0x1000. Usually,
> a RETF or

correction: 0xFFFF instead of 0x1000

0xFFFF for segment will put you 16 bytes below 1MB. Your offset
will adjust to 1MB.


RP



wolfgang kern

unread,
Mar 17, 2013, 5:20:21 AM3/17/13
to

Yeoj wrote:

>I can't figure out why my OS is not booting to the MB mark in memory.
>I have researched all I can and I am stuck.
>I am calling an assembly kernel.

Beside what Rod already pointed out, I got some daubt about the size
of your boot-image. The BIOS will only load the first 512 bytes from
a drive and execute this if the last two bytes swow 55 AA.
So the 'Fill' might undo many of your lines.

I see your code use int13/42 to load additional sectors, but methink
with all the TEXT and GDT/IDT setup in front of this, it might be far
off the 512 byte border.

BTW:
there's no need to jump over commented lines,
XOR will always clear the carry flag,
GDTR is ignored in Real-mode,
initial IDTR setting can be assumed to be 0,0 by BIOS anyway and
I hope you already cover all exceptions an IRQs before PM runs.

__
wolfgang

s_dub...@yahoo.com

unread,
Mar 18, 2013, 12:08:18 AM3/18/13
to
On Mar 16, 2:20 pm, Yeoj <joeytx1...@gmail.com> wrote:
> I can't figure out why my OS is not booting to the MB mark in memory. I have researched all I can and I am stuck. I am calling an assembly kernel.
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ; Yeoj Bootloader Version 1.0
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> %define version '1.0'
>
> [BITS 16]
> [ORG 0x7C00]
>
> main:
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ; main = whole program
> ; Move the location into DS
> ; Move Welcome String
> ; call Print to execute it
> ; JMP to Kernel to get there
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>  cli
>  mov ax,0x7C00  ; Setup the Data Segment register
>                 ; Location of data is DS:Offset
>  mov ds,ax      ; Now I know where I'm at

This isn't what you want, you have DS:Welcome set
to 7C00h:7CB1h - everything falls apart after this.
gdt limit=2048 isn't safe, you have only 3 descriptors you should
limit;
null, code, .data -- idt_48:,gdt_48: aren't descriptors.

121 0000006A [4A00]0000 dw gdt,0x0 ; gdt base = 0x0xxx
*this isn't the correct base, it needs to be the linear address; the
correct rm segment shifted left 4 bits + the offset of the gdt:.

I've used..

gdtr_desc: dw gdt_end - gdt - 1 ;; limit
gdtbase: dd 0 ;; base of gdt, _runtime_ fill.

.. and initialized it like this ..

mov eax, 0
mov eax, DS ;; 07C0h, as boot segment address.
shl eax, 4 ;; make segment a linear addr (7C00h)
mov ebx, eax ;; make a copy for alias_DS32 fixup
add eax, gdt ;; add offset to runtime segment, linear addr
mov [gdtbase], eax ;; store into gdtr descriptor

.. note DS was previously set to 07C0h because I chose to org my data
offsets to 0000h ..

;; code located at 0000:7C00. Chg data segment:offset to 07C0:0000h.
;;

START:
cli
mov ax, 07C0h
mov DS, ax
mov ES, ax
. . .
hth,
Steve

s_dub...@yahoo.com

unread,
Mar 18, 2013, 2:44:31 PM3/18/13
to
On Mar 17, 11:08 pm, "s_dubrov...@yahoo.com" <s_dubrov...@yahoo.com>
wrote:
> On Mar 16, 2:20 pm, Yeoj <joeytx1...@gmail.com> wrote:
>
>
> > I can't figure out why my OS is not booting to the MB mark in memory. I have researched all I can and I am stuck. I am calling an assembly kernel.
>
>
[snipped]
Oh, this pmode far jump needs to go there through a descriptor.
Something like: jmp 0008h:010000h

Steve
0 new messages