I switched form CBS to LBA in my bootloader, that loads a kernel after ata_lba_read in 32-bit mode Before this moment, I always tested my system with QEMU, and it worked (and works) perfectly there. Now I decided to try booting a system on a real hardware. It prints a boot message and restarts forever (kernel isn't loading) I searched answers for a while, but there were only those, that are already implemented in my bootloader.
Here's the bootloader code:
ORG 7C00h
[BITS 16]
CODE_SEG equ GDT_CODE - GDT_START
DATA_SEG equ GDT_DATA - GDT_START
jmp short start
nop
;FAT16 Header
OEM_Identifier db 'FAT16OEM'
BytesPerSector dw 0x200
SectorsPerCluster db 0x80
ReservedSectors dw 200
FATCopies db 0x02
RootDirEntries dw 0x40
NumberOfSectors dw 0
MediaType db 0xF8
SectorsPerFAT dw 0x100
SectorsPerTrack dw 0x20
NumberOfHeads dw 0x40
HiddenSectors dd 0x00
SectorsBig dd 0x773594
;Extended BPB
DriveNumber db 0x80
WinNTBit db 0x00
Signature db 0x29
VolumeID dd 0xD105
VolumeIDString db 'MYSTOS_BOOT'
SystemIDString db 'MOSFAT16'
start:
jmp 0x0:load
load:
cli
mov ax, 0x00
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x00
sti
mov cx, bootmsg
call print
mov cx, newline
call print
mov ax, 0xFFFF
mov cx, 0x2000
call sleep
.load_protected:
cli
lgdt[GDT_DESCRIPTOR]
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:load32
print:
push si
push bx
push ax
mov si, cx
mov bx, 0
print_loop:
lodsb
cmp al, 0
jz finish_print
call PrintChar
jmp print_loop
finish_print:
pop ax
pop bx
pop si
ret
PrintChar:
mov ah, 0Eh
int 10h
ret
sleep:
push ax
push cx
sleep_loop:
cmp cx, 0
jz dec_ax
dec cx
jmp sleep_loop
dec_ax:
cmp ax, 0
jz finish_sleep
dec ax
pop cx
push cx
jmp sleep_loop
finish_sleep:
pop cx
pop ax
ret
GDT_START:
GDT_NULL: ;64 bits of zeros
dd 0x0
dd 0x0
; offset 0x8
GDT_CODE: ;CS SHOULD POINT TO THIS
dw 0xFFFF ;Segment limit first 0-15 bits
dw 0 ;Base first 0-15 bits
db 0 ;Base 16-23 bits
db 0x9a ;Access byte
db 11001111b ;High and low 4 bit flags
db 0 ;Base 24-31 bits
; offset 0x10
GDT_DATA: ;DS, SS, ES, FS, GS
dw 0xFFFF ;Segment limit first 0-15 bits
dw 0 ;Base first 0-15 bits
db 0 ;Base 16-23 bits
db 0x92 ;Access byte
db 11001111b ;High and low 4 bit flags
db 0 ;Base 24-31 bits
GDT_END:
GDT_DESCRIPTOR:
dw GDT_END - GDT_START - 1
dd GDT_START
[BITS 32]
load32:
mov eax, 1
mov ecx, 128
mov edi, 0x0100000
call ata_lba_read
jmp CODE_SEG:0x0100000
ata_lba_read:
mov ebx, eax ;Backup the LBA
;Send the highest 8 bits of the LBA to harddisk controller
shr eax, 24 ;Shift 24 bits so eax now contain only the highest 8 bits of the LBA
or eax, 0xE0 ;Select the master drive
mov dx, 0x1F6
out dx, al ;Send
;Send the total sectors to read
mov eax, ecx
mov dx, 0x1F2
out dx, al
;Send more bits of the LBA
mov eax, ebx ;Restore LBA
mov dx, 0x1F3
out dx, al
;Send more bits of the LBA
mov eax, ebx ;Restore LBA
mov dx, 0x1F4
shr eax, 8 ;Shift 8 bits that were sent
out dx, al
;Send upper 16 bits of the LBA
mov eax, ebx ;Restore LBA
mov dx, 0x1F5
shr eax, 16 ;Shift 16 bits
out dx, al
;Finished sending
mov dx, 0x1F7
mov al, 0x20
out dx, al
;Read all sectors
.next_sector:
push ecx
;Checking the need to read
.try_again:
mov dx, 0x1F7
in al, dx
test al, 8
jz .try_again
;We need to read 256 words at a time
mov ecx, 256
mov dx, 0x1F0
rep insw
pop ecx
loop .next_sector
;End of reading
ret
bootmsg db 'www.https://stackoverflow.com/', 0
newline db 0Ah, 0Dh, 0
times 510-($-$$) db 0
dw 0xAA55
UPD: 32-bit print routine code (VGA Video Memory based on 0xB8000) Converted my working C print function to assembly one. The bootloader stops and prevents loading kernel in QEMU
makechar32: ;eax - chr, edx - color
shl edx, 8
or edx, eax
mov eax, edx
ret
putchar32: ;eax - chr, edx - color, ebx - x, ecx - y
call makechar32
mov esi, 0xB8000
;video_mem_saddr + y*80 + x
add esi, ebx
mov ebx, eax
mov eax, 80
mul ecx
mov ecx, eax
add esi, ecx
mov [esi], ebx
ret
printchar32: ;eax - chr, edx - color
pushad
mov ebx, [col]
mov ecx, [row]
call putchar32
inc ebx
cmp ebx, 80
jge newrow
newcol:
inc ebx
mov [col], ebx
popad
ret
newrow:
xor ebx, ebx
mov [col], ebx
inc ecx
mov [row], ecx
popad
ret
print32: ;ecx - *str
pushad
mov esi, ecx
print32_loop:
lodsb
cmp eax, 0
jz finish_print32
mov edx, 7
call printchar32
jmp print32_loop
finish_print32:
popad
ret