Here it is:
Code:
extern loader_end
extern lmain
section .entry
bits 16
global start
start:
mov ecx, [bx + 8]
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov gs, ax
mov eax, [loader_size]
shr eax, 9
inc eax
mov [dap.sectors], ax
mov eax, ecx
inc eax
mov [dap.lba], eax
mov [driveid], dl
mov sp, 0x8000
mov ah, 0x42
mov si, dap
int 0x13
jc .error
in al, 0x92
or al, 2
out 0x92, al
cli
lgdt [GDT32.Pointer]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:start32
.error:
mov si, disk_error
call print
jmp $
print:
lodsb
or al, al
jz .print_done
mov ah, 0x0e
int 0x10
jmp print
.print_done:
ret
loader_size dd loader_end - 0x8000
driveid db 0
dap:
.size db 0x10
.reserved db 0
.sectors dw 1
.offset dw 0x8200
.segment dw 0
.lba dd 0, 0
disk_error db 'Error: disk read failure!', 13, 10, 0
bits 32
GDT32:
.Null: equ $ - GDT32
dw 0
dw 0
db 0
db 0
db 0
db 0
.Code: equ $ - GDT32
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
.Data: equ $ - GDT32
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
.Code16: equ $ - GDT32
dw 0xFFFF
dw 0
db 0
db 10011010b
db 10001111b
db 0
.Data16: equ $ - GDT32
dw 0xFFFF
dw 0
db 0
db 10010010b
db 00001111b
db 0
.Pointer:
dw $ - GDT32 - 1
dd GDT32
section .text
start32:
xor eax, eax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x8000
call lmain
jmp $