I have a small "kernel" that is loaded in using my own Boot loader. The Boot loader loads the entire kernel(written in C) and sets the CPU to
32-bit and jumps to the kernel. And the kernel is loaded correctly. For accessing disk drive, I have a set of subroutines in assembly that switches the CPU back to
real mode, runs a BIOS I/O interrupt, switches back to 32-bit mode, get the stack back, and return back to C code.The Code snippet that I've posted below runs on emulators and my laptop with Insyde BIOS, but when tried to run on my old hardware, it freezes right at
int 0x13.
Code:
.
.
mov ah, 0x02
mov al, [0x7a00] ;1
mov cl, [0x7a01] ;1
mov dh, [0x7a02] ;31
mov dl, [drivedata] ;sets by bios
mov ch, [0x7a03] ;0
mov bx, [0x7a06] ;0
mov es, bx
mov bx, [0x7a04] ;0x7000
int 0x13
jnc diskreadnoerr
.
.
I have been using the same code snippet to run multiple filesystem based functions like list files, create new one, save to a file, read from a file etc. on both emulators and my real hardware. It worked with no problems, but when I tried to do the same on my old pc, it freezes.
And yes, I tested using debug-prints and found that the CPU executes successfully upto
int 0x13, then it doesn't come out. Doesn't go to error routine either. It stucks somewhere inside that routine.
I also tested by directly giving the arguments instead of reding it from memory, but still it didn't work. I have no idea why this is happening.
This is how I jumps back to real mode..
Code:
.
.
lgdt [gdt_desc_16]
jmp 0x8:$+7
mov eax, cr0
and al, 0xfe
mov cr0, eax
jmp 0x0:bit_16_start
[bits 16]
bit_16_start:
mov ax, 0
mov ds, ax
mov ss, ax
mov fs, ax
mov es, ax
mov gs, ax
mov ax, 0x7900
mov sp, ax
mov bp, ax
.
.
Don't know if this is needed, but here is the 16-bit protected mode gdt I used:
Code:
null_16: ;NULL gdt
dd 0x0
dd 0x0
gdt_code_16: ;code segment descriptor
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 00001111b
db 0x0
gdt_data_16: ;Data segment Descriptor
dw 0xffff
dw 0x0
db 0x0
db 10010010b ; 1 st flags , type flags
db 00001111b ; 2 nd flags , Limit ( bits 16 -19)
db 0x0
EDIT: I found something. I am more confused now.
I can actually call some BIOS routines! I used 10h to reset video mode and used my own 16-bit subroutine to that prints strings using 10h and it all worked! Right until int 0x13!
Then I tried to reset disk using int 13h. But no even that didn't happen.
my modified code:
Code:
[bits 16]
mov dl, 0x80
mov ah, 0
;int 0x13 ;doesn't work!
mov al, 3
mov ah, 0
int 0x10 ; works!
mov bx, checkdata
call print_bx ;also works!
mov al, [0x7a00]
mov cl, [0x7a01]
mov dh, [0x7a02]
mov dl, [drivedata]
mov ch, [0x7a03]
mov bx, [0x7a06]
mov es, bx
mov bx, [0x7a04]
mov ah, 0x02
int 0x13 ;doesn't work!
If real mode has problem, how am I able to call a function from the boot loader to print a string but not even reset the disk system?!