Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 从iso映像引导为什么引导加载程序的内存地址不是0x7c00_Assembly_X86_Bootloader_Osdev_Iso Image - Fatal编程技术网

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

Assembly 从iso映像引导为什么引导加载程序的内存地址不是0x7c00,assembly,x86,bootloader,osdev,iso-image,Assembly,X86,Bootloader,Osdev,Iso Image,我写了一个用于学习的小引导加载程序,它将打印出引导加载程序的第一条指令的内存地址,它肯定是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 # star

我写了一个用于学习的小引导加载程序,它将打印出引导加载程序的第一条指令的内存地址,它肯定是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
在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引导规范的一种常见误解,即默认情况下,模拟引导扇区应在“传统的7C0段”加载。它并没有说应该使用非传统的起始地址07C0:0000而不是传统的0000:7C00,但是BIOS编写者将此解释为一种要求

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

  jmp $0x07c0,$start
start:

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

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

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

  jmp $0x07c0,$start
start:

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

您的call/pop获得CS:IP地址的偏移部分。BIOSes可以使用两种方式来寻址线性地址7C00:要么
07C0:0000
(就像您的代码如何设置DS),要么
0000:7C00
。其中一个是正式正确的,但真正的系统做另一个并不罕见;我忘了哪个是哪个。但是在实践中,如果你的代码不能同时处理这两种情况,那就是一个问题。你的call/pop会得到CS:IP地址的偏移部分。BIOSes可以使用两种方式来寻址线性地址7C00:要么
07C0:0000
(就像您的代码如何设置DS),要么
0000:7C00
。其中一个是正式正确的,但真正的系统做另一个并不罕见;我忘了哪个是哪个。但在实践中,如果您的代码不能同时处理这两种情况,那就是一个问题。