Jump to content

Cannot switching into the protected mode?

- - - - -

  • Please log in to reply
5 replies to this topic

#1
sebo

sebo

    Newbie

  • Members
  • Pip
  • 4 posts
Hello :) I wanna make a small operating system in c. its just ought to show hello world. offcourse i need a assembly(nasm) bootloader. i have make it and its goes. so, now i must switch into the protected mode but that didn't goes....i allready make a ckernel, .... but i dont know, why i cant switch into the protected mode. please help me! here the code:

kernel_asm.asm

mov ax, 1000h

mov ds, ax

mov es, ax


[BITS 16]

start:


mov si, msg

call putstr

call getkey


msg db "switching into the protected mode....", 13, 10, "please press any key to switch into the protected mode.....",  0



putstr:

lodsb

or al, al

jz short putstrd

mov ah, 0x0E

mov bx, 0x0007

int 0x10

jmp putstr


putstrd:

retn


getkey:

mov ah, 0

int 0x16

jmp switch


switch:

mov ah, 0x0e

mov al, 0x0d

int 0x10

mov al, 0x0a

int 0x10

%include "gdt.inc"

cli

lgdt[gdtr]

mov eax, cr0

or al, 1

mov cr0, eax


jmp 08h:Pmode


[BITS 32]

Pmode:

mov ax, datasel

mov ds, ax

mov ss, ax

mov esp, 0x9000

jmp 0x8:0x4000


times 512 - ($-$$) hlt

gdt.inc

gdtr:				

   dw gdt_end-gdt-1		

   dd gdt			

gdt:

   dd 0,0			

codesel equ $-gdt

   dw 0xFFFF			

   dw 0x0000			

   db 0x00			

   db 0x9A			

   db 0xCF			

   db 0x00			

datasel equ $-gdt

   dw 0xFFFF			

   dw 0x0000			

   db 0x00			

   db 0x92			

   db 0xCF			

   db 0x00			

gdt_end:

ckernel.c

unsigned int k_printf(char* message, unsigned int line)

{

    char* vidmem = (char*) 0xb8000;

    unsigned int i = line*80*2;


    while(*message!=0)

    {

        if(*message==0x2F)

        {

            *message++;

            if(*message==0x6e)

            {

                line++;

                i=(line*80*2);

                *message++;

                if(*message==0){return(1);};

            };

        };

        vidmem[i]=*message;

        *message++;

        ++i;

        vidmem[i]=0x0A;

        ++i;

    };

    return 1;

};


int main()

{

	k_printf("hello", 12);

	return 0;

}

	

link.ld

OUTPUT("binary")

INPUT("ck.o")

ENTRY("main")

SECTIONS

{

	.text 0x4000 :

	{

		*(.text)

	}

	.data :

	{

		*(.data)

	}

	.bss :

	{

		*(.bss)

	}

}


please help me! thanks!

#2
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
When does the problem come in?

Is your program loaded for booting (it's just it doesn't have a 'dw 0xAA55' at the end, what boot sectors are supposed to have)? Or does the program not print the "... press any key" message? Or does it to something weird after you press any key?

#3
sebo

sebo

    Newbie

  • Members
  • Pip
  • 4 posts
its so: the os.img is build of boot.bin kernel_asm.bin ckernel.bin. its booting, but the code isnt here. the problem comes when the press any key message comes.

#4
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Maybe try using '%include "gdt.inc"' after the code and right before the "times 512 ..." ?

#5
sebo

sebo

    Newbie

  • Members
  • Pip
  • 4 posts
no...its doesnt goes...worser: you cant use the getkey funtion, i dont know why. becauso of this i have cut out the funtion.

here the code:
mov ax, 1000h

mov ds, ax

mov es, ax


[BITS 16]

start:


mov si, msg

call putstr

jmp switch


msg db "switching into the protected mode....", 13, 10, "please press any key to switch into the protected mode.....",  0



putstr:

lodsb

or al, al

jz short putstrd

mov ah, 0x0E

mov bx, 0x0007

int 0x10

jmp putstr


putstrd:

retn


switch:

cli

lgdt[gdtr]

mov eax, cr0

or al, 1

mov cr0, eax


jmp 08h:Pmode


[BITS 32]

Pmode:

mov ax, datasel

mov ds, ax

mov ss, ax

mov esp, 0x9000

jmp 0x8:0x4000


%include "gdt.inc"


times 512 - ($-$$) hlt


#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
You have a very bad habit of interspersing your code and data. The assembler is probably going to keep those in the same locations, so the program will try and execute your data, resulting in weird things happening. Always put it all at the end of your loader, or somewhere else where execution will never go. Here's one I wrote:

bootloader.asm


bits    16

cpu     8086

org     7c00h


%assign     KERNEL_SECTOR_COUNT 0x40

%assign     KERNEL_START_SECTOR 0x02

%assign     KERNEL_LOAD_SEGMENT 0x0000

%assign     KERNEL_LOAD_OFFSET  0x8000


;__load:

;    jmp     __start

;    %if ($-$$) < 3

;        nop

;    %endif


;__DISK_INFORMATION:

;    ; this needs to be filled with the FAT32 information

;    times 87 db 0


; CODE

__start:

    ; disable interrupts

    .init_stack:

        cli

        ; save this drive number

        mov     [thisdrive], dl

        ; set up stack and data segments

        xor     ax, ax

        mov     ds, ax

        mov     ss, ax

        mov     sp, 7900h

        sti


    ; change video mode

    mov     ax, 0003h

    int     10h


    ; clear the screen

    mov     ax, 0600h

    mov     bh, 07h

    xor     cx, cx

    mov     dx, 184fh

    int     10h


    ; try to enable A20 using the BIOS

    mov     ax, 2401h

    int     15h

    jnc     .load_kernel                    ; if CF=1 then we failed.


    ; okay, we failed. try another method.

    ; go through keyboard controller

    in      al, 92h

    or      al, 02h

    out     92h, al

    ; check to see if A20 is enabled

    call    _check_a20


    ; If carry flag is set then we failed again. Print error and hang.

    jnc     .load_kernel


    ; If we get here then A20 failed. print no A20 error message

    mov     si, msg_err_a20

    call    _print


    ; fall through and hang.

    .hang:

        cli

        hlt


    .load_kernel:

        ; print "kernel loading" message

        mov     si, msg_loading

        call    _print


        ; reset the disk controller

        mov     ah, 00h

        mov     dl, [thisdrive]

        int     13h

        jc      .load_reset_failed


        ; load the kernel code

        mov     ah, 02h                     ; int 13h, subfunction 02h

        mov     al, KERNEL_SECTOR_COUNT     ; number of sectors to read

        mov     ch, 00h                     ; starting cylinder

        mov     cl, KERNEL_START_SECTOR     ; starting sector, base 1

        mov     dh, 00h                     ; head

        mov     dl, [thisdrive]             ; drive number

        mov     bx, KERNEL_LOAD_SEGMENT     ;

        mov     es, bx                      ;

        mov     bx, KERNEL_LOAD_OFFSET      ; kernel loads at ES:BX

        int     13h


        jc      .load_failed                ; disk read failure on carry


        ; jump to kernel

        jmp     [p_loadaddr]


    .load_reset_failed:

        mov     si, msg_err_dskrst

        call    _print

        jmp     .hang


    .load_failed:

        mov     si, msg_err_disk

        call    _print

        jmp     .hang


_print:

    mov     ah, 0eh

    mov     bx, 0007h


    ._printloop:

        ; load the next char to print

        lodsb

        ; test for end of string

        cmp     al, 00h

        je      .done_print

        ; print character

        int     10h

        ; go on to next

        jmp     ._printloop


    .done_print:

    ret


; FUNCTION TO CHECK WHETHER A20 IS ENABLED

_check_a20:

    ;disable interrupts

    cli

    push    ds


    ; ES = 0, DS = 0ffffh

    xor     ax, ax

    mov     es, ax

    not     ax

    mov     ds, ax


    ; DI = 0500h, SI = 0510h

    mov     di, 0500h

    mov     si, 0510h


    ; Note that because without A20 we're limited to 1 megabyte of memory, if

    ; A20 isn't enabled then high addresses will wrap around. Because of segmen-

    ; tation in 8086 mode, ES:[DI] and DS:[SI] (0000h:0500h and ffffh:0510h

    ; respectively) should map to the same memory address. So all we have to do

    ; is store a value to ES:[DI] and read it back from DS:[SI]. If we get the

    ; same value, then we're guaranteed that A20 isn't enabled. If we don't get

    ; the same value, then A20 is definitely on.


    cmpsw

    jne     .a20_ok


    ; we got the same value back. If we write something different to each and

    ; get the same value in both then we've got A20 disabled.

    mov     WORD [es:di], 0cafeh

    mov     WORD [ds:si], 0deadh

    cmp     WORD [es:di], 0deadh

    jne     .a20_ok


    ; if we get here then A20 is definitely disabled. Set carry flag and exit.

    .a20_disabled:

        stc

        jmp     .exit


    ; If we get here then A20 is enabled. Clear carry flag and exit.

    .a20_ok:

        clc


    .exit:

        pop     ds

        sti

        ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; CONSTANT DATA

msg_err_a20:    db  "Could not enable high memory.",00h

msg_err_disk:   db  "Disk read error.",00h

msg_err_dskrst: db  "Disk reset error.",00h

msg_loading:    db  "Loading kernel from disk...",00h

p_loadaddr:     dw  KERNEL_LOAD_OFFSET, KERNEL_LOAD_SEGMENT

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; VARIABLE DATA

thisdrive:      db  0


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

%if 420-($-$$) < 0

    %error "FATAL ERROR: Boot code is over 420 bytes long."

%endif


times 510-($-$$) db 0cch


db 55h

db 0aah


loader-stage2.asm

bits    32

cpu     686

org     0x8000


__start:

; load GDT

mov     eax, gdt_start

lgdt    [eax]

mov     eax, cr0

or      eax, 1

mov     cr0, eax

jmp     0x08:[loader_entry]


loader_entry:

; load kernel from the disk here

; ...

; jump into kernel

jmp     [kernel_entry]


kernel_entry:   dd  KERNEL_ENTRY_POINT


gdt_start:

    gdt limit: dw  gdt_end - gdt_start

    gdt_table:

        %include "gdt.inc"

gdt_end:


%include "basic-fat32.drv.inc"


If this makes no sense, here's a great tutorial on how to do all of this (including the IDT).
sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users