Home > Software engineering >  How to read sector into memory and jump to it for OS?
How to read sector into memory and jump to it for OS?

Time:11-05

I know this question gets asked a lot but every answer I find doesn't work for me. I'm trying to load stage 2 of my OS, located at the second sector of my image file(0x200)

This is the code I tried to use:


bits 16                             ; Starting at 16 bits
org 0x0                               ; And starting at 0

jmp main                            ; Hop to main!


; TODO: copy comment from prev. loader
; args: SI
print:
    lodsb                           ; Load the next/first character to AL
    or al, al                       ; Is it 0?
    jz donePrint                    ; Yes - Done.
    mov ah, 0eh                     ; No - keep going.
    int 10h                         ; Print character.
    jmp print                       ; Repeat
donePrint:
    ret                             ; Return


; todo: args
readSector:
    mov ah, 02h
    mov al, 1
    mov dl, 0x80
    mov ch, 0
    mov dh, 0
    mov cl, 2

    mov bx, 0x500


    int 13h
    jnc good
    jmp fail

main:
    ; First, setup some registers.
    cli                             ; Clear interrupts
    mov ax, 0x07C0                  ; Point all registers to segment
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Create the stack(0x0000-0xFFFF).
    mov ax, 0x0000
    mov ss, ax                      ; Point SS to 0x0000
    mov sp, 0xFFFF                  ; Stack pointer at 0xFFFF
    sti                             ; Restore interrupts

    mov si, LOADING
    call print

    call readSector

    

    
fail:
    mov si, FAILURE_MSG
    call print
    
good:
    mov si, LOADOK 
    call print
    jmp 0x500

LOADING        db 0x0D, 0x0A, "Booting loader...", 0x0D, 0x0A, 0x00
FAILURE_MSG    db 0x0D, 0x0A, "ERROR: Press any key to reboot.", 0x0A, 0x00
LOADOK    db 0x0D, 0x0A, "load ok", 0x0A, 0x00



TIMES 510 - ($-$$) DB 0
DW 0xAA55

But it just bootloops. I tried other solutions to no avail. What am I doing wrong? If I need to update the question please tell me.

Thank you!

EDIT #1: According to Sep Roland's answer, I updated my code, but it is still not working. I'm putting the updated code here if it's any help. Also, if asked for it, I can post my 2nd stage code. It should be using 0x500 as org. NEW CODE:

bits 16                             ; Starting at 16 bits
org 0x0                             ; And starting at 0

jmp main                            ; Hop to main!


; TODO: copy comment from prev. loader
; args: SI
print:
    lodsb                           ; Load the next/first character to AL
    or al, al                       ; Is it 0?
    jz donePrint                    ; Yes - Done.
    mov ah, 0eh                     ; No - keep going.
    int 10h                         ; Print character.
    jmp print                       ; Repeat
donePrint:
    ret                             ; Return


; todo: args
readSector:
    mov ah, 02h
    mov al, 1
    mov ch, 0
    mov dh, 0
    mov cl, 2

    mov bx, 0x500


    int 13h
    jnc good
    jmp fail

main:
    ; First, setup some registers.
    cli                             ; Clear interrupts
    mov ax, 0x07C0                  ; Point all registers to segment
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Create the stack(0x0000-0xFFFF).
    mov ax, 0x0000
    mov ss, ax                      ; Point SS to 0x0000
    mov sp, 0xFFFE                  ; Stack pointer at 0xFFFE
    sti                             ; Restore interrupts

    mov si, LOADING
    call print

    call readSector

    

    
fail:
    mov si, FAILURE_MSG
    call print
end:
    cli
    hlt
    jmp end
    
good:
    mov si, LOADOK 
    call print
    jmp 0x07C0:0x0500

LOADING        db 0x0D, 0x0A, "Booting loader...", 0x0D, 0x0A, 0x00
FAILURE_MSG    db 0x0D, 0x0A, "ERROR: Press any key to reboot.", 0x0A, 0x00
LOADOK    db 0x0D, 0x0A, "load ok", 0x0A, 0x00



TIMES 510 - ($-$$) DB 0
DW 0xAA55

EDIT #2: Posting second stage code including gdt.inc because someone mentioned LGDT may have been causing a problem:

MAIN CODE(SOME PARTS HAVE BEEN CUT OUT BUT THEY ARE NOT REQUIRED, like strings)

bits 16                                 ; We start at 16 bits

org 0x500                               ; We are loaded in at 0x500

jmp main                                ; Jump to main code.


; ----------------------------------------
; Includes
; ----------------------------------------
%include "include/stdio.inc"
%include "include/gdt.inc"
%include "include/a20.inc"


; ---------------------------------------
; Data and strings
; ---------------------------------------

stringhidden db "Not showing string.", 0x0D, 0x0A, 0x00
stringhidden db "Not showing string.", 0x0D, 0x0A, 0x00

; ---------------------------------------------------------------------
; main - 16-bit entry point
; Installing GDT, storing BIOS info, and enabling protected mode
; ---------------------------------------------------------------------

main:
    ; Our goal is jump to main32 to become 32-bit

    ; Setup segments and stack
    cli                                 ; Clear interrupts
    xor ax, ax                          ; Null segments AX, DS, and ES
    mov ds, ax
    mov es, ax
    mov ax, 0x9000                      ; Stack begins at 0x9000-0xFFFF
    mov ss, ax
    mov sp, 0xFFFF                      ; Stack pointer is 0xFFFF
    sti                                 ; Enable interrupts

    

    ; Install the GDT
    call installGDT                     ; Install the GDT

    ; Enable A20
    call enableA20_KKbrd_Out            ; Enable A20 through output port

    ; Print loading messages
    mov si, msg1
    call print16                        ; Print the message

    mov si, msg2                        ; A message
    call print16                        ; Print the message

    ; Enter protected mode
    cli                                 ; Clear interrupts
    mov eax, cr0                        ; Set bit 0 in CR0--ENTER protected mode
    or eax, 1
    mov cr0, eax

    jmp CODE_DESC:main32                ; Far jump to fix CS
    
    ; We can't re-enable interrupts because that would triple-fault. This will be fixed in main32.


bits 32                                 ; We are now 32 bit!

%include "include/stdio32.inc"

main32:
    ; Set registers up
    mov ax, 0x10                        ; Setup data segments to 0x10(data selector)
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov esp, 90000h                     ; Stack begins from 90000h
    
    call clear32                        ; Clear screen
    mov ebx, MSGHIDDEN                   ; Setup params for our message
    call puts32                         ; Call puts32 to print

    cli                                 ; Clear interrupts
    hlt                                 ; Halt the processor

LGDT CODE:

%ifndef __GDT_INC_67343546FDCC56AAB872_INCLUDED__
           
  • Related