Page 1 of 1

Jumping to Kernel Offset

Posted: Sun Aug 09, 2009 4:25 pm
by brodeur235
My boot loader is all 16 bit code. It enters protected mode, and then jumps to the kernel which is coded in 32 bit. When I jump to my kernel, if the offset of the kernel (in memory) is greater than one WORD, then I get a nasm warning and my kernel isn't run:

Code: Select all

jmp 0x08:0x00010000
I can load the kernel there, but I can't jump to it... How can this be fixed?

Brodeur235

Re: Jumping to Kernel Offset

Posted: Sun Aug 09, 2009 4:49 pm
by Combuster
Tell nasm to emit a 32 bit jump rather than a 16 bit jump

Code: Select all

jmp dword 0x0008:0x00010000

Re: Jumping to Kernel Offset

Posted: Sun Aug 09, 2009 7:49 pm
by brodeur235
Thanks Combuster that works very well... Apparently I'm also having trouble loading the kernel to anything higher than a WORD address. I am using int 0x13 to raw read the disk image / floppy. The BIOS call reads the specified data on disk to es:bx. This seems simple enough however, until now I have been determining the memory location to load the kernel to like this:

Code: Select all

xor bx,bx
mov es,bx
mov bx,kern_offset
Obviously that won't work to load the kernel to an address larger than 1 word, so I modified it to this:

Code: Select all

mov ebx,kern_offset
shr ebx,0x00000010
mov es,bx
mov ebx,kern_offset
But for one reason or another I am still only able to load the kernel to an address lower than 1 word.
Here is the entire kernel loading procedure:

Code: Select all

kernel_loader:
	
	; determine # of sectors to load
	; dx:ax / bx = ax remainder dx
	mov dx,0x0000
	mov ax,KERNEL_SIZE
	mov bx,SECTOR_SIZE
	div bx
	
	; ensure size is even number of sectors
	cmp dx,0x0000
	jnz .kl_error
	
	; setup to loop thru sectors
	mov cx,ax
	mov BYTE [ BLOC( sector_current ) ], KERNEL_SECTOR
	mov DWORD [ BLOC( offset_current ) ], KERNEL_OFFSET
	.kl_copy_sector:
		push cx
		
		; copy current sector
		; disk loc -> es:bx in mem
		mov dh,KERNEL_DRIVE
		mov dl,KERNEL_HEAD
		mov ch,KERNEL_TRACK
		mov cl,[ BLOC( sector_current ) ]
		
		; setup destination ( es:bx)
		mov eax,DWORD [ BLOC( offset_current ) ]
		shr eax,0x00000010
		mov es,ax
		mov ebx,DWORD [ BLOC( offset_current ) ]
		
		
		mov ah,0x02
		mov al,0x01
		int 0x13
		
		; prepare for next sector
		add DWORD [ BLOC( offset_current ) ],SECTOR_SIZE
		inc BYTE [ BLOC( sector_current ) ]
		
		pop cx
		loop .kl_copy_sector
	
	; completed
	jmp .kl_success
	
	; error section
	.kl_error:
		jmp $
	
	; success section
	.kl_success:
		ret

bl_data:
	
	; kernel_load data
	sector_current db 0x00 ; KERNEL_SECTOR
	offset_current dd 0x00000000 ; KERNEL_OFFSET
KERNEL_SIZE is the size of the kernel in bytes and BLOC() is just a macro that adds 0x7C00 to an input variable. Does anyone see something wrong? Keep in mind this works for loading the kernel to an address lower than 1 word...

Brodeur235

Re: Jumping to Kernel Offset

Posted: Tue Aug 11, 2009 5:02 am
by egos
You can reset es on each sector reading or only when 128 sectors (64 kb) have been read:

Code: Select all

  add bx,0200h ; bh,02h
  jnz @f
  mov ax,es
  add ax,1000h ; ah,10h
  mov es,ax
@@: