Page 1 of 2

[Solved] BIOS Int 13/02h hangs the bootloader

Posted: Sat Jan 27, 2018 9:27 pm
by PaulAche
I am writing a simple bootloader and currently having a problem loading the kernel into the memory from disk. When I try to read disk sectors, int13/02h never returns and hangs the execution of the program. I managed to make the bootloader print a hello-message prior to making the interrupt (int 10/Eh), so the boot signature is ok and the bootloader code is being run.

I'd like to read 1 sector, and here are my registers at the execution address of int13/02h (checked with debugging):

ax: 0x201
bx: 0x8000 (my kernel offset)
cx: 0x02
dx: 0x80
sp: 0xffff

ss: 0x9000
ds: 0x07c0 (will set to 0x0 before ljumping to kernel)
es: 0x0

It seems like I am experiencing something similar to this, except that I am setting up the es:bx buffer correctly, so the correct answer doesn't really help me.

Code: Select all

	movw  $0x0, %bx
	movw  %bx, %es
	movw  $0x8000, %bx
Needless to say, I am pretty new to this. I hope anyone can point me in the right direction, and hopefully the information I've provided is sufficient.

Edit
ss: 0x9000 (previously 0x7000)

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sat Jan 27, 2018 11:43 pm
by TightCoderEx
Post your entire code, that way those of us helping won't have to make so many assumptions about what it might be.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 8:00 am
by PaulAche
Edit: The code served no purpose in solving this issue. This was caused by the stack segment overriding the EBDA sector.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 9:51 am
by iansjack
What's the return code from the BIOS call?

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 10:32 am
by PaulAche
iansjack wrote:What's the return code from the BIOS call?
That is what I am getting at. There is no return, the bootloader just hangs when it tries to execute the int13/02h line.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 11:33 am
by iansjack
How do you know it is "hanging"?

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 11:46 am
by PaulAche
iansjack wrote:How do you know it is "hanging"?
I've run bochs with gdb and set 2 breakpoints, one at

Code: Select all

 int $0x13 
and another at

Code: Select all

cmpb $0x0, %ah
(the instruction right after int13/2h).

It hits the first breakpoint at

Code: Select all

 int $0x13 
I am able to interact with the debugger, e.g. "info registers", "continue". However, when I type "continue" to resume the execution, bochs hangs and the gdb becomes irresponsive. It never reaches the 2nd breakpoint:

Code: Select all

cmpb $0x0, %ah
Bochs hangs without the gdb as well.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 12:36 pm
by PaulAche
PaulAche wrote: Edit
ss: 0x9000 (previously 0x7000)
I am very sorry for confusing everyone. I had my %ss register set to 0x9000, not 0x7000 as stated previously. After actually changing it to 0x7000 the bootloader no longer hanged and I was able to read the sector (returned ah=0). My initial thought was that my read was somehow overwriting the stack. However, I was only reading 1 sector (512 bytes) at the address 0x8000, so that can't be the case. Could anyone explain?

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 1:04 pm
by davidv1992
After the complete read, you have only 512 bytes of stack space left. It is very well possible that your bios uses more than that internally.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 1:16 pm
by TightCoderEx
#1: Your string is not NULL terminated
#2: Don't hardcode DL, what it needs to be has already been passed by BIOS
#3: Trace into the code @ 8000H, cause that's probably where the problem is.

In Boch's, just single step to next instruction after BIOS function and see what's returned in AH or set your breakpoint @ cmp $0x0, %ah

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 1:58 pm
by Octocontrabass
PaulAche wrote:Could anyone explain?
Your stack was colliding with the EBDA. Take a look at this memory map for example.

(You should also be setting SP to 0, not 0xFFFF.)

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 2:15 pm
by PaulAche
Octocontrabass wrote:
PaulAche wrote:Could anyone explain?
Your stack was colliding with the EBDA. Take a look at this memory map for example.

(You should also be setting SP to 0, not 0xFFFF.)
Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision. Also, why should the sp be set to 0?

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 2:27 pm
by PaulAche
TightCoderEx wrote:#1: Your string is not NULL terminated
#2: Don't hardcode DL, what it needs to be has already been passed by BIOS
#3: Trace into the code @ 8000H, cause that's probably where the problem is.
#1. asciz, z stands for zero. They are null terminated.
#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
#3. It would be nice if I could, but the gdb hangs during the execution.
TightCoderEx wrote: In Boch's, just single step to next instruction after BIOS function and see what's returned in AH or set your breakpoint @ cmp $0x0, %ah
I couldn't single step/trace/info registers because both Bochs and the GDB hung during (not after) the execution of 0x13.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 2:47 pm
by Octocontrabass
PaulAche wrote:Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision.
With SS set to 0x9000, your stack segment covers the entire (linear) address range from 0x90000 to 0x9FFFF, which includes the small section reserved for use by the EBDA. You put your stack right at the top, where the EBDA goes.
PaulAche wrote:Also, why should the sp be set to 0?
In the x86 architecture, SP always points to the item at the top of the stack. When the stack is completely empty, SP should point just past the topmost space in the stack. If the first byte to be filled by a push is at 0xFFFF, then SP should point to one byte higher: 0.

Wasting one byte of stack space is no big deal, but having the stack misaligned can be a big performance hit, and compiled code requires the stack to be aligned.

(For contrast, some non-x86 CPU architectures have their equivalent of SP pointing to the empty space at the top of the stack. In these architectures, setting the stack pointer to 0xFFFF would be correct.)
PaulAche wrote:#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
Almost all BIOSes will set DL for you, including every PnP BIOS (which is everything from the mid-90s onward). Hardcoding it means you'll have problems the first time you encounter a BIOS that doesn't assign 0x80 to your boot disk.

Re: BIOS Int 13/02h hangs the bootloader

Posted: Sun Jan 28, 2018 3:18 pm
by PaulAche
Octocontrabass wrote:
PaulAche wrote:Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision.
With SS set to 0x9000, your stack segment covers the entire (linear) address range from 0x90000 to 0x9FFFF, which includes the small section reserved for use by the EBDA. You put your stack right at the top, where the EBDA goes.
PaulAche wrote:Also, why should the sp be set to 0?
In the x86 architecture, SP always points to the item at the top of the stack. When the stack is completely empty, SP should point just past the topmost space in the stack. If the first byte to be filled by a push is at 0xFFFF, then SP should point to one byte higher: 0.

Wasting one byte of stack space is no big deal, but having the stack misaligned can be a big performance hit, and compiled code requires the stack to be aligned.

(For contrast, some non-x86 CPU architectures have their equivalent of SP pointing to the empty space at the top of the stack. In these architectures, setting the stack pointer to 0xFFFF would be correct.)
PaulAche wrote:#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
Almost all BIOSes will set DL for you, including every PnP BIOS (which is everything from the mid-90s onward). Hardcoding it means you'll have problems the first time you encounter a BIOS that doesn't assign 0x80 to your boot disk.
Your explanation makes perfect sense! The only thing I'm struggling with is understanding how you got the linear address range from 0x9000. If I remember correctly, I can get the linear address by SS * 16 + SP. That would make the address range start at (0h * 16h) + 9000h = 0x90000 (20-bit value). How did you get the upper range value 0x9FFFF?