从 iso 映像引导为什么引导加载程序的内存地址不是 0x7c00

Booting from iso image why memory address of bootloader is not 0x7c00

为了学习写了一个小bootloader,会打印出bootloader第一条指令的内存地址,肯定是0x7c00。看下面的汇编源码是运行好

boot.s

.code16
.global init
init:
  mov [=10=]x07c0, %ax
  mov %ax, %ds
  mov [=10=]x07e0, %ax
  mov %ax, %ss
  mov [=10=]x2000, %sp

  call next
next:
  pop %bx
  sub $(next-init), %bx  # starting point of memory address, now stored in %bx
  call print_register
  jmp .

print_register:  # always print out value in %bx
  mov %bh, %cl
  shr [=10=]x4, %cl
  and [=10=]x0f, %cl
  call print_digit
  mov %bh, %cl
  and [=10=]x0f, %cl
  call print_digit
  mov %bl, %cl
  shr [=10=]x4, %cl
  and [=10=]x0f, %cl
  call print_digit
  mov %bl, %cl
  and [=10=]x0f, %cl
  call print_digit
  ret

print_digit: # %cl has digit to be printed
  cmp [=10=]x9, %cl
  jg print_digit_atof
print_digit_1to9:
  add [=10=]x30, %cl
  jmp print_digit_out
print_digit_atof:
  add [=10=]x57, %cl
print_digit_out:
  mov %cl, %al
  mov [=10=]x0e, %ah
  int [=10=]x10
  ret

.=510
.byte 0x55
.byte 0xaa
as -o boot.o boot.s
ld -o boot.bin --oformat binary -e init boot.o

在VMWare Player中创建虚拟机,将boot.bin设置为软盘内容,然后开机。我可以在屏幕上看到 7c00

到目前为止一切顺利。

参考这个答案,但是现在如果我通过以下命令将boot.bin作为引导加载程序放入iso映像中:

dd if=/dev/zero of=floppy.img bs=1024 count=1440
dd if=boot.bin of=floppy.img seek=0 count=1 conv=notrunc
mkdir iso
cp floppy.img iso/
genisoimage -quiet -V 'MYOS' -input-charset iso8859-1 -o myos.iso -b floppy.img \
    -hide floppy.img iso/

并使用 myos.iso 启动虚拟机,屏幕上显示 0000

为什么不是7c00


已更新 阅读答案后,当我打印出 %cs 时,我可以看到:

1. boot from floppy disk, start address is 0x0000:7c00
2. boot from cd rom, start address is 0x07c0:0000

这是由于对 El Torito CD-ROM 引导规范的常见误解造成的,该规范认为模拟引导扇区默认应加载到 "traditional segment of 7C0"。它并没有说应该使用非传统的起始地址 07C0:0000 来代替传统的 0000:7C00,但是 BIOS 作者仍然将此解释为一项要求。

虽然您可以假定您的引导扇区加载到线性地址 00007C00 并且 BIOS 在引导扇区的第一个字节开始执行您的代码,但您不能假定任何特定值 CS:IP.虽然大多数引导扇区可以编写为不依赖于加载到 CS 中的段值,因为 near JMP 和 CALL 指令是相对的,如果你这样做,那么你需要在你的代码中放置一个 far JMP 指令以确保 CS 加载了预期的段值:

  jmp [=10=]x07c0,$start
start:

注意上面例子中段(0x07c0)的选择是基于你的bootsector的"org"为0,所以假设bootsector第一个字节的偏移量是0 而不是 0x7c00。这意味着将上面的代码添加到引导扇区的开头,它将始终打印 0000.