Weird int 0x13 behaviour in real environment
Posted: Tue Mar 05, 2019 2:01 pm
Hi, this is my first post, as I'm starting to make my own operating system. The Wiki part of this site already helped me a lot !
I'm still at the beginning of the project, stuck at the bootloader level.
This bootloader is very basic ; its final version will read sector 2 of the initial disk (a USB drive), place it in the RAM, go into 32-bit protected mode, and far jump to the memory where the 2nd sector was loaded.
The problem I'm facing only occurs on my real-life Toshiba Satellite Pro NB10-A, and I don't have any other real-life ressource to try my bootloader on.
Here is my current bootloader : It only loads sector 2 and print its first byte as an ascii character, without jumpping to it.
Here is the source for gdt.asm (Global Descriptor Table)
Here is a description of the problem:
A. Loading in qemu-system-i386 :
This code works flawlessly : the "X" (black on white) is displayed in the top-left corner.
B. Loading in my Toshiba :
The top-left corner shows an empty white box (null byte interpreted as ascii, shown as whitespace).
While debugging with a custom print function displaying hexadecimal, I realised that when reading sector 1, it works well (a "3" is displayed at the top left, ascii 51), but when reading sector 2, the buffer is full of zeros. The carry register indicates normal behaviour, and the number in "al", the number of sectors actually read, is 1 (correct). But, the buffer is actually full of zeros. I tried different addresses for the buffer, I checked a lot of registers, tried some solutions I found in the web. None solved the problem, but what's worse is that I don't understand where it could come from : I specified correct parameters of the interrupt 0x13,2, so why does the real environment won't let me access this sector ? Grub loads flawlessly on this device, so I'm the one missing something.
Also, This USB drive does not contain any partitionning system at this state of the project.
To compile my project :
real-life (z my USB drive) : ..\..\fasm\FASM.EXE ath_os.asm ath_os.bin && dd if=ath_os.bin of=\\.\z: bs=512 count=2
qemu : ..\..\fasm\FASM.EXE ath_os.asm ath_os.bin && "C:\Program Files (x86)\qemu\qemu-system-i386w.exe" -hda ath_os.bin
I also tried putting the .bin to my USB drive with rufus and with dd on linux.
I'm attaching the full code including disk_load, print, and debug functions.
Also I'm a beginner in assembly but I'll do my best to understand complex answers.
I'm still at the beginning of the project, stuck at the bootloader level.
This bootloader is very basic ; its final version will read sector 2 of the initial disk (a USB drive), place it in the RAM, go into 32-bit protected mode, and far jump to the memory where the 2nd sector was loaded.
The problem I'm facing only occurs on my real-life Toshiba Satellite Pro NB10-A, and I don't have any other real-life ressource to try my bootloader on.
Here is my current bootloader : It only loads sector 2 and print its first byte as an ascii character, without jumpping to it.
Code: Select all
org 0x7c00
use16
jmp main
bootdrv:db 0
include "gdt.asm" ; global descriptor table
main:
; read "disk"
; dl already set
mov ah, 0x02 ; Read Sector : stanislavs.org/helppc/int_13-2.html
mov bx, 0 ; temporarily 0
mov al, 1 ; read 1 sector
mov ch, bl ; cylinder 0
mov cl, 2 ; select sector 2 (reading sector 1 works correctly)
mov dh, bl ; head 0
mov es, bx ; buffer segment : 0
mov bx, 0x9000 ; buffer address (es:bx) : 0*16 + 0x9000 = 0x09000
int 0x13 ; interrupt call
; switching to 32-bit pm mode
cli ; clear interrupts
lgdt [gdt_descriptor] ; load gdt
mov eax, cr0 ; real switch (setting flag)
or eax, 0x1
mov cr0, eax
; far jump (still in this 1st sector) :
jmp CODE_SEGMENT:init_protected_mode
use32
init_protected_mode:
mov ax, DATA_SEGMENT ; set all the segments (cs was set when far-jumping)
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov edx, 0xb8000 ; set edx to the video memory (no more interrupts to print !)
mov al, [0x9000] ; place in al the byte in 0x9000 (where the sector was loaded, should be "X")
mov ah, 0xf0 ; character style : black on white (easily found in screen)
mov [edx], ax ; setting the video memory (the change is seen in the top-left corner)
jmp $ ; hang
times 510-($-$$) db 0 ; fill with zeros
dw 0xaa55 ; magic bytes to allow bootable drive
; second sector starts here
db "X"
Code: Select all
gdt_start:
gdt_null_descriptor:
dd 0, 0
gdt_code_descriptor:
dw 0xffff, 0
db 0, 10011010b, 11001111b, 0
gdt_data_descriptor:
dw 0xffff, 0
db 0, 10010010b, 11001111b, 0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEGMENT equ gdt_code_descriptor - gdt_start
DATA_SEGMENT equ gdt_data_descriptor - gdt_start
A. Loading in qemu-system-i386 :
This code works flawlessly : the "X" (black on white) is displayed in the top-left corner.
B. Loading in my Toshiba :
The top-left corner shows an empty white box (null byte interpreted as ascii, shown as whitespace).
While debugging with a custom print function displaying hexadecimal, I realised that when reading sector 1, it works well (a "3" is displayed at the top left, ascii 51), but when reading sector 2, the buffer is full of zeros. The carry register indicates normal behaviour, and the number in "al", the number of sectors actually read, is 1 (correct). But, the buffer is actually full of zeros. I tried different addresses for the buffer, I checked a lot of registers, tried some solutions I found in the web. None solved the problem, but what's worse is that I don't understand where it could come from : I specified correct parameters of the interrupt 0x13,2, so why does the real environment won't let me access this sector ? Grub loads flawlessly on this device, so I'm the one missing something.
Also, This USB drive does not contain any partitionning system at this state of the project.
To compile my project :
real-life (z my USB drive) : ..\..\fasm\FASM.EXE ath_os.asm ath_os.bin && dd if=ath_os.bin of=\\.\z: bs=512 count=2
qemu : ..\..\fasm\FASM.EXE ath_os.asm ath_os.bin && "C:\Program Files (x86)\qemu\qemu-system-i386w.exe" -hda ath_os.bin
I also tried putting the .bin to my USB drive with rufus and with dd on linux.
I'm attaching the full code including disk_load, print, and debug functions.
Also I'm a beginner in assembly but I'll do my best to understand complex answers.