move to protect mode fail. the bochs reboot.

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
shellex
Posts: 12
Joined: Sat Nov 17, 2007 8:35 am

move to protect mode fail. the bochs reboot.

Post by shellex »

a error occurs when i load my os to bochs and bochs reboot. i don't know what mistake i made.
can u help me? i have work on it for several days.... : (
thx. :)

Code: Select all

.code16
.global _start

_start:

    #; clear screen
    mov     $0x0600,     %ax
    mov     $0x0000,    %cx
    mov     $0x174f,    %dx
    mov     $0x00,    %bh
    int     $0x10

    xorw    %ax,    %ax     #; ax <- zero
    movw    %ax,    %ds     #; DS <- zero
    movw    %ax,    %ss     #; stack starts at 0x00
    movw    $0x9c00,    %sp #; 200h past code start
    movw    $0xb800,    %ax #; text video memory
    movw    %ax,    %es     


    push    $sx_os_logo
    push    $0x000A
    call    _vprint_str 

    push    $sx_os_boot_msg
    push    $0x000E
    call    _vprint_str 

enable_a20:        
    inb    $0x64,   %al    
    testb  $0x2,    %al
    jnz    enable_a20
    movb   $0xbf,   %al
    outb   %al,     $0x64

#;load GDT
    lgdt gdt_seg         #; load gdt with whatever is appropriate  

#;set cr0 = 1,
    movl   %cr0,    %eax
    orl    $0x1,    %eax
    movl   %eax,    %cr0    
#;move to protect mode
    ljmp $8,$0


.code32:
protc_seg:
    
#;write a char to memory
    mov $0x0f01,     %bx   #; attrib/char of smiley
    mov $0x0b800,    %eax  #; note 32 bit offset
    movw %bx,     %ds:(%eax)    
#; loop forever 
    jmp     .

#;-------------------------------------

.p2align 2 /* force 4-byte alignment */ 
gdt:
    .word   0x0000, 0x0000     #;NULL
    .byte   0x00, 0x00, 0x00, 0x00
code_segment:
    .word   0xFFFF          #;4Gb - (0x100000 * 0x1000 = 4Gb)
    .word   0x0000          #;base address
    .byte   0x00, 0x9A      #;code read/exec
    .byte   0xCF, 0x00      #;granularity
data_segment:
    .word   0xFFFF          #;4Gb - (0x100000 * 0x1000 = 4Gb)
    .word   0x0000          #;base address
    .byte   0x00, 0x92      #;data read/write
    .byte   0xCF, 0x00      #;granularity
videoseg:
    .word 0x3999, 0x8000
    .byte 0x0b, 0x92, 0x00, 0x00
bootrealseg:
    .word 0xffff, 0
    .byte 0, 0x9e, 0x00, 0
bootrealdata:
    .word 0xffff, 0
    .byte 0, 0x92, 0x00, 0

gdt_len = . - gdt
gdt_seg:
    .word gdt_len - 1        #; gdt limit
    .word 0x7c00 + gdt, 0 #; gdt base


#;-------------------------------------

sx_os_logo:
    .asciz  "     --== ShellEx OS [version 0.0.0.1]==--  "
sx_os_logo_length = . - sx_os_logo

sx_os_boot_msg:
    .asciz  "     [i]Loading ...."
sx_os_boot_msg_length = . - sx_os_boot_msg

    .org    510, 0x90               
    .word    0xaa55         
 
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Re: move to protect mode fail. the bochs reboot.

Post by XCHG »

There are three things that I noticed in your code that are kind of fishy:

Code: Select all

enable_a20:       
    inb    $0x64,   %al   
    testb  $0x2,    %al
    jnz    enable_a20
    movb   $0xbf,   %al
    outb   %al,     $0x64 
I don't know why you are sending the value of 0xBF to the on-board Keyboard Microcontroller. To enable the A20 Gate, I do this:

1) Make sure Bit#1 of Status Byte at port 0x64 is zero.
2) Output 0xD0 to port 0x64 to retrieve the output port's value in port 0x60.
3) I poll Bit#0 of port 0x64 and I wait for it to become 1 so that I know there is data available at port 0x60.
4) I then read the value in port 0x60. Bit#1 in this value should be set for the A20 gate to be enabled.
5) I then poll port 0x64 and I wait for the bit#1 to be zero.
6) I then send the value 0xD1 to port 0x64 so that the next byte I send to port 0x60 would be the new value with A20 set.
7) I wait for Bit#1 in port 0x64 to become zero again.
8) I then take the value I got in step 4, OR it with 0x02 to set Bit#1 (A20 gate) and then I will send it to port 0x60. Done.


This is the code that I have written in NASM for enabling the A20 gate:

Code: Select all

  .EnableA20Pin:
    .WaitForInput1:
      IN      AL , 0x64
      TEST    AL , 0x02
      JNZ     .WaitForInput1
    MOV     AL , 0xD0
    OUT     0x64 , AL
    .WaitForOutput1:
      IN      AL , 0x64
      TEST    AL , 0x01
      JZ      .WaitForOutput1
    IN      AL , 0x60
    MOV     AH , AL
    .WaitForInput2:
      IN      AL , 0x64
      TEST    AL , 0x02
      JNZ     .WaitForInput2
    MOV     AL , 0xD1
    OUT     0x64 , AL
    .WaitForInput3:
      IN      AL , 0x64
      TEST    AL , 0x02
      JNZ     .WaitForInput3
    MOV     AL , AH
    OR      AL , 0x02
    OUT     0x60 , AL

The second thing that I noticed was the [gdt_seg] label. This label, as you have it right now is 32-bits long:

Code: Select all

gdt_seg:
    .word gdt_len - 1        #; gdt limit
    .word 0x7c00 + gdt, 0 #; gdt base
the LGDT instruction takes a 48-bit long data structure where the first 16-bit is the size of GDT-1 and the next DWORD is the base address of GDT. This is how I have created this in my Second Stage Boot Loader:

Code: Select all

; ——————————————————————————————————————————————————
GDTR:
  DW      (GDT_END - GDT) - 0x01
  DD      GDT
; ——————————————————————————————————————————————————
Notice that the limit is a DW (WORD, 16-bits) and the base address is DD (DWORD, 32-bits).


The third thing that is not quite clear to me is how you are printing messages to the screen. None of the strings in your code are null-terminated. I think you need to mark the end of your strings with a character. But then again, that's your call.

I hope this helped.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
shellex
Posts: 12
Joined: Sat Nov 17, 2007 8:35 am

Post by shellex »

Thank you very much for your help :). but problems are stil.....l
1.the code to enable A20 gate is come from web. i am not know it clearly. e...is it necessary? i got another way to open A20 in a book named `build os yourself':

Code: Select all

in al, 92h
or al, 00000010b
out 92h, al
the author of the book say it's one of the simplest way to enable A20 gate.

2.i have correct the code in your description. but it not work.
this is my code :

Code: Select all

.code16
.global _start

CODE_SEL    = 0x08      

_start:
/*
    #; clear screen
    mov     $0x0600,     %ax
    mov     $0x0000,    %cx
    mov     $0x174f,    %dx
    mov     $0x00,    %bh
    int     $0x10
*/
    xorw    %ax,    %ax     #; ax <- zero
    movw    %ax,    %ds     #; DS <- zero
    movw    %ax,    %ss     #; stack starts at 0x00
    movw    $0x9c00,    %sp #; 200h past code start
    movw    $0xb800,    %ax #; text video memory
    movw    %ax,    %es     


    push    $sx_os_logo
    push    $0x000A
    call    _vprint_str 

    push    $sx_os_boot_msg
    push    $0x000E
    call    _vprint_str 



#; enable a20
#; is it necessary?
    inb    $0x92,   %al    
    or     $0x2,    %al
    outb   %al,     $0x92

#;load gdt
    lgdt gdt_seg         #; load gdt with whatever is appropriate  
 
#;PE = 1 / 0;
#;move to Protected Mode/Real Mode;
#;set cr0 = 1,
    movl   %cr0,    %eax
    orl    $0x1,    %eax
    movl   %eax,    %cr0    
#;move to protect mode
#;how can it work?
    ljmp $8, $0


.code32:
protc_seg:
    
#;print a char to video memory
    mov $0x0f01,     %bx   #; attrib/char of smiley
    mov $0x0b800,    %eax  #; note 32 bit offset
    movw %bx,     %ds:(%eax)    

#   movb     $0x00,  %ah
#   int     $0x16            #; await keypress using BIOS
#   int     $0x19            #; reboot
    jmp     .



.include "print.S"

#;-------------------------------------

.p2align 2 /* force 4-byte alignment */ 
gdt:
    .word   0x0000, 0x0000     #;NULL
    .byte   0x00, 0x00, 0x00, 0x00
code_segment:
    .word   0xFFFF          #;4Gb - (0x100000 * 0x1000 = 4Gb)
    .word   0x0000          #;base address
    .byte   0x00, 0x9A      #;code read/exec
    .byte   0xCF, 0x00      #;granularity
data_segment:
    .word   0xFFFF          #;4Gb - (0x100000 * 0x1000 = 4Gb)
    .word   0x0000          #;base address
    .byte   0x00, 0x92      #;data read/write
    .byte   0xCF, 0x00      #;granularity
videoseg = . - gdt
    .word 0x3999, 0x8000
    .byte 0x0b, 0x92, 0x00, 0x00
bootrealseg = . - gdt
    .word 0xffff, 0
    .byte 0, 0x9e, 0x00, 0
bootrealdata = . - gdt
    .word 0xffff, 0
    .byte 0, 0x92, 0x00, 0
 
gdt_seg:
    .word  . - gdt - 0x01               #; gdt limit
    .int gdt                            #; gdt base

#;-------------------------------------

sx_os_logo:
    .asciz  "     --== ShellEx OS [version 0.0.0.1]==--  "
sx_os_logo_length = . - sx_os_logo

sx_os_boot_msg:
    .asciz  "     [i]Loading ...."
sx_os_boot_msg_length = . - sx_os_boot_msg

    .org    510, 0x90               
    .word    0xaa55             


3.i use this function to print msg to screen:
all my string use `asciz'. they are null-terminated.

Code: Select all

#; write string text video memory (without SIOS interrupt)
_vprint_str:   
    push    %bp
    movw    %sp,    %bp
    xor     %bx,    %bx
    movw    4(%bp), %bx     #; param 2: attrib
    movw    6(%bp), %si     #; param 1: string

_vprint_str_loop:
    xor  %ax,   %ax
    lodsb                   #; load string from si to AL
    cmp $0,     %al
    je _vprint_str_done
    movb %bl,    %ah
    push %ax                #; attrib = (0000:0000, bg:fg)
    call _vprint_char
    pop  %ax
    jmp _vprint_str_loop
_vprint_str_done:
    addb $1,    ypos        #;down one row
    movb $0,    xpos         #;back to left
    pop     %bp
    ret
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Please could you post (inside code tags) the final Bochs register dump when your code triple-faults.

Cheers,
Adam
User avatar
shellex
Posts: 12
Joined: Sat Nov 17, 2007 8:35 am

Post by shellex »

thx all and i have solve the problem. i just try to load kernel to a fixed address, and it's works well.
:) :lol:
User avatar
Dandee Yuyo
Member
Member
Posts: 47
Joined: Fri Nov 09, 2007 6:46 pm
Location: Argentina

Post by Dandee Yuyo »

A20 is needed to address odd memory banks above 1MB.
NaN - Not a Nerd
Working on: Physical Memory Management with a 5-lod mipmap XD
Post Reply