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__