从 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

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

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

jmp $0x07c0,$start
start:

请注意,在上面的示例中,段 (0x07c0( 的选择是基于您的引导扇区的"org"为 0 的事实,因此假定引导扇区的第一个字节的偏移量为 0 而不是 0x7c00。 这意味着将上述代码添加到引导扇区的开头,它将始终打印0000

相关内容

  • 没有找到相关文章

最新更新