Assembly BIOS int 0x13修改CS:IP?

Assembly BIOS int 0x13修改CS:IP?,assembly,gdb,x86-16,bootloader,real-mode,Assembly,Gdb,X86 16,Bootloader,Real Mode,我正在编写一个x86引导加载程序,它占用磁盘上的两个部分(1024字节),我希望它做的第一件事是在继续执行之前将这两个部分加载到段0x60 以下是我的代码的重新定位部分: _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,

我正在编写一个x86引导加载程序,它占用磁盘上的两个部分(1024字节),我希望它做的第一件事是在继续执行之前将这两个部分加载到段
0x60

以下是我的代码的重新定位部分:

_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
这似乎不起作用,但是,我试图用gdb调试代码,除了一个普通二进制文件之外,我还创建了一个ELF文件
boot.ELF
,并在将gdb附加到运行我的二进制文件的qemu进程之后执行
addsymbol file boot.ELF 0x60
,然后执行
break reloc_done
。我本来希望
继续
然后实际命中
0x60:reloc_done
处的断点,但这没有发生。这里怎么了

当我单步执行这个程序时,它看起来像是
int$0x13
实际上将CS:IP修改为
F000:E3FE
,我完全不理解这一点

编辑:尝试整合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);
  }
}
编译如下:

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
然后被复制到磁盘映像的第一个扇区。现在执行的初始指令不是mov$0x60,%ax,而是完全不同的东西


另一个编辑:我想我现在明白了,我必须按照MichaelPetch的建议更改链接器脚本中的链接地址,但也要从代码中删除初始的
jmp$0x0,
,这已经没有意义了。

每种函数调用、分支或中断都会修改CS:IP。看起来你的调试器进入了BIOS代码。@interjay:你说得对,CS:IP在中断后确实指向BIOS ROM,我没有意识到,我以为gdb的“下一步”会跨过中断。@MichaelPetch:我使用的是处理段:偏移寻址的gdb脚本。我现在要做的是首先中断
jmp 0x60:reloc_done
指令,然后在地址
0x600
处重新加载
boot.elf
(在我的问题中,我使用了
0x60
,这显然是错误的)。当我继续单步执行时,它一开始似乎起作用,但随后指令/装配线似乎被随机跳过,因此仍然存在一些问题。我认为问题是,在jmp之后,CS是
0x60
,这很好,但是对于CS:IP,IP应该减少
0x7C00
,以指向我希望它指向的地方。但我不知道如何做到这一点,GAS拒绝jmp$0x60,$reloc_done-$0x7C00@MichaelPetch:我不确定我是否理解,我的链接器脚本以
开头0x7C00。文本:{…
,即加载地址
0x7C00
和链接地址(默认情况下,我假设,因为在(0)处添加
不会改变任何内容)零。每种函数调用、分支或中断都会修改CS:IP。看起来你的调试器进入了BIOS代码。@interjay:你说得对,在中断后CS:IP确实指向BIOS ROM,我没有意识到,我以为gdb的“下一步”将跳过中断。@MichaelPetch:我正在使用一个处理段:偏移寻址的gdb脚本。我现在要做的是首先中断
jmp 0x60:reloc_done
指令,然后在地址
0x600
处重新加载
boot.elf
(在我的问题中,我使用了
0x60
,这显然是错误的)。当我继续单步执行时,它一开始似乎起作用,但随后指令/装配线似乎被随机跳过,因此仍然存在一些问题。我认为问题是,在jmp之后,CS是
0x60
,这很好,但对于CS:IP,IP应该减少
0x7C00
,以指向我希望它指向的位置。但是我我不知道如何做到这一点,GAS拒绝了
jmp$0x60,$reloc_done-$0x7C00
@MichaelPetch:我不知道我是否理解,我的链接器脚本以
=0x7C00;开始。文本:{…
,即加载地址
0x7C00
和链接地址(默认情况下我假设,因为在(0)
处添加
不会改变任何东西)零。