Загрузка с образа 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
.