问题
I'm writing an x86 bootloader which occupies two sections (1024 bytes) on disk and the first thing I want it to do is to load both sections to segment 0x60
before continuing execution
Here is the relocation part of my code:
_start:
// relocate and load remaining bootloader code
mov $0x60, %ax
mov %ax, %es
mov $0x02, %ah
mov $2, %al
xor %bx, %bx
mov $0, %ch
mov $2, %cl
xor %dh, %dh
int $0x13
jmp $0x60, $reloc_done
reloc_done:
// set up segment registers
mov $0x60, %ax
mov %ax, %ds
mov %ax, %es
// set up stack
mov $0x8000, %bx
mov %bx, %ss
xor %ax, %ax
mov %ax, %sp
This does not seem to work however, I have tried to debug my code with gdb by creating an ELF file boot.elf
in addition to a flat binary and executing add-symbol-file boot.elf 0x60
followed by break reloc_done
after attaching gdb to the qemu process running my binary. I would have expected a continue
to then actually hit the breakpoint at 0x60:reloc_done
but this doesn't happen. What's wrong here?
When I single step through this program, it looks like the int $0x13
actually modifies CS:IP to F000:E3FE
which I do not understand at all.
EDIT: A minimal example trying to integrate some suggestions by MichaelPetch:
boot.S:
// real mode code
.code16
.global _start
jmp $0x0, $_start
_start:
mov $0x8000, %ax
mov %ax, %sp
// relocate and load remaining bootloader code
mov $0x60, %ax
mov %ax, %es
xor %bx, %bx
mov $0x02, %ah
mov $2, %al
mov $0, %ch
mov $1, %cl
xor %dh, %dh
int $0x13
jmp $0x60, $reloc_done
reloc_done:
nop
// set up segment registers
mov $0x60, %ax
mov %ax, %ds
mov %ax, %es
// set up stack
mov $0x8000, %bx
mov %bx, %ss
xor %ax, %ax
mov %ax, %sp
boot.ld:
OUTPUT_FORMAT("elf32-i386");
ENTRY(_start);
SECTIONS
{
. = 0x0;
.text : {
*(.text);
. = 510;
SHORT(0xAA55);
}
.data : SUBALIGN(2) {
*(.data);
*(.rodata*);
}
/DISCARD/ : {
*(.eh_frame);
*(.comment);
}
}
Compiled like this:
gcc -m32 -fno-PIC -g -gdwarf -Wall -Werroro -c asm/boot.S -o out/boot_S.o
ld -melf_i386 -Tout/boot.ld out/boot_S.o -o ../elf/boot.elf
objcopy -O binary ../elf/boot.elf ../img/boot.img
boot.img
is then copied to the first sector of a disk image. Now the initial instruction executed is not mov $0x60, %ax
but something else entirely.
ANOTHER EDIT: I think I got it now, I had to change the link address in my linker script as suggested by MichaelPetch but then also remove the initial jmp $0x0, ...
from my code which didn't make sense anymore.
来源:https://stackoverflow.com/questions/64987706/bios-int-0x13-modifies-csip