Bootloader: Jumping to stage 2

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Mr. Newbie

Bootloader: Jumping to stage 2

Post by Mr. Newbie »

Hi Folks,

I'm playing around with writing an x86 bootloader just for learning purposes. I'm just trying to put together a simple two stage boot loader.

Now the problem is, whatever I do I seem to get the following error from Bochs:

Bochs is exiting with the following message:
[CPU ] prefetch: RIP > CS.limit

The log output is:

00002474308p[CPU ] >>PANIC<< prefetch: RIP > CS.limit
00002474308i[SYS ] Last time is 1135666120
00002474308i[XGUI ] Exit.
00002474308i[CPU ] real mode
00002474308i[CPU ] CS.d_b = 16 bit
00002474308i[CPU ] SS.d_b = 16 bit
00002474308i[CPU ] | EAX=0fff2000 EBX=00000000 ECX=00110102 EDX=00000153
00002474308i[CPU ] | ESP=0000fffe EBP=00000000 ESI=00007c7d EDI=0000ffde
00002474308i[CPU ] | IOPL=0 NV UP DI PL ZR NA PE NC
00002474308i[CPU ] | SEG selector base limit G D
00002474308i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00002474308i[CPU ] | CS:2000( 0000| 0| 0) 00020000 0000ffff 0 0
00002474308i[CPU ] | DS:2000( 0000| 0| 0) 00020000 0000ffff 0 0
00002474308i[CPU ] | SS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00002474308i[CPU ] | ES:2000( 0000| 0| 0) 00020000 0000ffff 0 0
00002474308i[CPU ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00002474308i[CPU ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00002474308i[CPU ] | EIP=00010000 (00010000)
00002474308i[CPU ] | CR0=0x00000010 CR1=0 CR2=0x00000000
00002474308i[CPU ] | CR3=0x00000000 CR4=0x00000000
00002474308i[ ] restoring default signal behavior
00002474308i[CTRL ] quit_sim called with exit code 1


I read one sector on the floppy, as follows:

mov $0x2000, %bx # Segment location to read into
mov %bx, %es
mov $0x0, %bx # Offset to read into
mov $0x2, %ah # BIOS read sector function
mov $0x1, %al # Read just 1 sector
mov $0x1, %ch # Read track 1
mov $0x2, %cl # Read the second sector
mov $0x1, %dh # Read from the first head
mov 0x0, %dl # Read from drive 0
int $0x13 # Perform the BIOS call

and then jump to the new location:

mov $0x2000, %ax # New data segment
mov %ax, %ds
jmp $0x2000, $0x0000

I'm compiling the first and second stages as follows:

as -o stage1.o stage1.s
ld --oformat binary --Ttext 0x7C00 -o stage1.bin stage1.o

as -o stage2.o stage2.s
ld --oformat binary --Ttext 0x0000 -entry=_stage2 -o stage2.bin stage2.o

dd if=stage1.bin of=floppy.img bs=512 count=1
dd if=stage2.bin of=floppy.img bs=512 count=1 seek=1

Any idea why "RIP > CS.limit" ? 0x2000:0x0000 would indeed be below the 1Mb mark if my understanding of real mode addressing is correct.
Ytinasni

Re:Bootloader: Jumping to stage 2

Post by Ytinasni »

Mr. Newbie wrote: 00002474308p[CPU ] >>PANIC<< prefetch: RIP > CS.limit
00002474308i[CPU ] | EIP=00010000 (00010000)
Any idea why "RIP > CS.limit"?
You'll notice bochs stops at 0x2000:0x10000.

My (educated) guess is that you're reading a sector of zeroes, and executing "add [bx+si],al" or "add [eax],al" (opcode 0x0,0x0) lots.

Since bochs' memory is initialized to all zeroes, this continues until it gets to the 64K real-mode segment limit.

The cause is that, while sector numbers are 1-based, head and cylinder numbers aren't, and you read from sector 2, head 1, cylinder 1.

(The solution, obviously, is to read from sector 2, head 0, cylinder 0, and you'll get the sector you dd'd to your floppy image instead of an empty :)
Mr. Newbie

Re:Bootloader: Jumping to stage 2

Post by Mr. Newbie »

Thanks Ytinasni,

You got it in one! With your suggestion it now works as I expected.

Much appreciated!
Post Reply