Page 1 of 1

Kernel crashes if code extends beyond 2 sectors

Posted: Thu Jan 13, 2005 1:21 pm
by mztan
Hello everyone. Please excuse the newbocity of my post, but I've been actively perusing this site as well as osdever.net and I can't figure out what is wrong. I have a bootsect.asm, which loads GDT's, IDT's, Protected Mode, enables A20 and jumps to my main kernel, which is written in C. So far all my code does is print a welcome message, and loops while waiting for keyboard input. Everything works just great, except, when my main kernel (plus the misc. functions, like in,out,print, etc) gets to be bigger than 1KB (2 sectors), it just crashes and reboots endlessly. Can someone help me?

(Currently it is at exactly 1KB, and it works like a charm. I will post code if it's necessary.)

Thanks

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Thu Jan 13, 2005 2:07 pm
by IRBMe
Sounds like the boot loader is fouling up but without any more detail, who knows why.

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Thu Jan 13, 2005 2:20 pm
by mztan
Here is the first half of my bootloader code: (I know some assembly, but this is strictly a copy-paste job...)

Code: Select all

[BITS 16]       ; We need 16-bit intructions for Real mode
[ORG 0x7C00]    ; The BIOS loads the boot sector into memory location 0x7C00
origin equ 0x7C00
GLOBAL entry

entry:
reset_drive:
        mov ah, 0               ; RESET-command
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        mov ax, 0
        mov es, ax
        mov bx, 0x1000          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command
        mov al, 02h             ; Number of sectors to read = 1
        mov ch, 0               ; Cylinder = 0
        mov cl, 02h             ; Sector = 2
        mov dh, 0               ; Head = 0
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        cli                     ; Disable interrupts, we want to be alone

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 08h:clear_pipe      ; Jump to code segment, offset clear_pipe


[BITS 32]                       ; We now need 32-bit instructions
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

;Set up IDT tables..
   
   lidt [idt_pointer]
   call read_kbd
   call enable_A20
   
   call read_kbd

        jmp 08h:01000h          ; Jump to section 08h (code), offset 01000h

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Thu Jan 13, 2005 2:22 pm
by mztan
The 2nd half:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Random code bits
;;;;;;;;;;;;;;;;;;;;;;;;;;

read_kbd:
        in al,64h       ; read status byte
   and al,01h      ; wait for OBF==1
        jz read_kbd
        in al,60h       ; read scancode byte
        ret

printchar:
   mov ah,0x0E    ; This number is the number of the function in the BIOS to run.
   mov bh,0x00    ; Page number (I'm not 100% sure of this myself but it is best
   mov bl,0x07    ; Text attribute (Controls the background and foreground colour
   mov al,65
   int 0x10    ; Call the BIOS video interrupt.
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;
;; End random code bits
;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Enable A20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

enable_A20:
        cli

        call    a20wait
        mov     al,0xAD
        out     0x64,al

        call    a20wait
        mov     al,0xD0
        out     0x64,al

        call    a20wait2
        in      al,0x60
        push    eax

        call    a20wait
        mov     al,0xD1
        out     0x64,al

        call    a20wait
        pop     eax
        or      al,2
        out     0x60,al

        call    a20wait
        mov     al,0xAE
        out     0x64,al

        call    a20wait
        ;sti
        ret

a20wait:
.l0:    mov     ecx,65536
.l1:    in      al,0x64
        test    al,2
        jz      .l2
        loop    .l1
        jmp     .l0
.l2:    ret


a20wait2:
.l0:    mov     ecx,65536
.l1:    in      al,0x64
        test    al,1
        jnz     .l2
        loop    .l1
        jmp     .l0
.l2:    ret


start_of_idt:
  ;interrupt 0
  dw isr1   
  dw 0x10
  dw 0x8E00
  dw (origin >> 16)
 
  ;interrupt 1
  dw isr1
  dw 0x10
  dw 0x8E00
  dw (origin >> 16)
end_of_idt:

idt_pointer:
  dw end_of_idt - start_of_idt - 1
  dd start_of_idt

;;;;;;;;;;;;;;;;;;;;;;;;;
;; ISRs
;;;;;;;;;;;;;;;;;;;;;;;;;

isr1:
  pusha
  push gs
  push fs
  push es
  push ds   

  ;call
  ;jmp printchar
  mov word [0xB8000],'D '

  pop ds
  pop es
  pop fs
  pop gs
  popa
  iret

gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:                ; Used to calculate the size of the GDT

gdt_desc:                       ; The GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                  ; Address of the GDT

times 510-($-$$) db 0           ; Fill up the file with zeros

        dw 0AA55h                ; Boot sector identifyer

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Fri Jan 14, 2005 3:10 am
by Pype.Clicker
i'm not surprised it doesn't load kernels bigger than 1K since it only reads 2 sectors ...

e.g. look at your "loading" code: you have hard-coded "mov al,2" thus you'll always try to load 2 sectors... That's one of the reason why GRUB is so nice to use.

I'm not yet using it and it means i need to use ad-hock ASM-code patching tools (sue me) to tell the bootloader how much sectors it should read and from where ...

Oh, also ... You should know that INT13 will probably not allow more than 18 sectors to be read at once (actually, no more than one track at once), so when you'll have something like >9K, expect more weirdnesses to occur :)

Welcome to the real mode (err... i mean world)

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Fri Jan 14, 2005 7:33 am
by distantvoices
me neither: the poor cpu, working so brave just to be thrown into silicium nirvana. No wonder it says *sigh, I don't want anymore ... ?rks*

Re:Kernel crashes if code extends beyond 2 sectors

Posted: Fri Jan 14, 2005 9:16 am
by mztan
Ah great thanks. I was looking through my bootloader last night and I noticed this.

While I'm here, I have another question. What is the option to have the strings in my code be written to the end of the binary file? I vaguely remember reading about that somewhere. Would that be a reason why I am unable to print literal strings? (i.e. print("Hello, world!");)

Thanks again