Загрузка с образа iso, почему адрес памяти загрузчика не равен 0x7c00

Я пишу небольшой загрузчик с учебной целью, который распечатает адрес памяти первой инструкции загрузчика, это определенно 0x7c00. См. Ниже исходный код сборки работает нормально.

boot.s

.code16
.global init
init:
  mov $0x07c0, %ax
  mov %ax, %ds
  mov $0x07e0, %ax
  mov %ax, %ss
  mov $0x2000, %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 $0x4, %cl
  and $0x0f, %cl
  call print_digit
  mov %bh, %cl
  and $0x0f, %cl
  call print_digit
  mov %bl, %cl
  shr $0x4, %cl
  and $0x0f, %cl
  call print_digit
  mov %bl, %cl
  and $0x0f, %cl
  call print_digit
  ret

print_digit: # %cl has digit to be printed
  cmp $0x9, %cl
  jg print_digit_atof
print_digit_1to9:
  add $0x30, %cl
  jmp print_digit_out
print_digit_atof:
  add $0x57, %cl
print_digit_out:
  mov %cl, %al
  mov $0x0e, %ah
  int $0x10
  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 напечатано на экране.

Все идет нормально.

См. Этот ответ Создание загрузочного ISO-образа с пользовательским загрузчиком, но теперь, если я поставлю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

1 ответ

Решение

Это вызвано распространенным неправильным толкованием спецификации загрузки CD-ROM El Torito, в которой говорится, что эмулируемые загрузочные сектора по умолчанию должны загружаться в "традиционный сегмент 7C0". В нем не говорится, что вместо традиционного 0000:7C00 следует использовать нетрадиционный начальный адрес 07C0: 0000, но, тем не менее, разработчики BIOS интерпретировали это как требование.

Хотя вы можете предположить, что ваш загрузочный сектор загружен по линейному адресу 00007C00 и что BIOS начинает выполнение вашего кода с первого байта загрузочного сектора, вы не можете предполагать какое-либо конкретное значение CS:IP. Хотя большинство загрузочных секторов можно написать так, чтобы они не зависели от значения сегмента, загруженного в CS, так как инструкции JMP и CALL являются относительными, если у вас есть, то вам нужно поместить дальнюю инструкцию JMP в свой код, чтобы убедиться, что CS загружен с ожидаемым значение сегмента:

  jmp $0x07c0,$start
start:

Обратите внимание, что выбор сегмента (0x07c0) в приведенном выше примере основан на том факте, что ваш загрузочный сектор имеет "org", равный 0, так что смещение первого байта загрузочного сектора предполагается равным 0, а не 0x7c00. Это означает, что с приведенным выше кодом, добавленным в начало вашего загрузочного сектора, он будет последовательно печатать0000.

Другие вопросы по тегам