简体   繁体   中英

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

I write a small bootloader for study purpose, which will print out the memory address of the first instruction of the bootloader, it is definitely 0x7c00. See below assembly source code is running well.

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

In VMWare Player, create a virtual machine, and set boot.bin as the content of the floppy disk, then power on. I can see 7c00 printed on the screen.

So far so good.

Refer to this answer Creating a bootable ISO image with custom bootloader , But now if I put the boot.bin as a bootloader into an iso image by following commands:

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/

and boot the virtual machine with myos.iso , on screen is shows 0000 .

Why it is not 7c00 ?


Updated after reading the answer, when I print out %cs, I could see:

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

It's caused because of a common misinterpretation of the El Torito CD-ROM boot specification which says that emulated bootsectors should be loaded at the "traditional segment of 7C0" by default. It doesn't say that a non-traditional starting address of 07C0:0000 should be used instead of the traditional 0000:7C00, but BIOS writers have interpreted this as a requirement nonetheless.

While you can assume that your bootsector is loaded at a linear address of 00007C00 and that the BIOS starts execution of your code at the first byte of the bootsector, you can't assume any particular value of CS:IP. While most bootsectors can be written not to depend on the segment value loaded into CS, as near JMP and CALL instructions are relative, if yours does then you'll need to put a far JMP instruction your code to ensure CS is loaded with the expected segment value:

  jmp $0x07c0,$start
start:

Note that the choice of segment (0x07c0) in the example above is based on the fact that your bootsector has an "org" of 0, so that the offset of the first byte of bootsector is assumed to be 0 rather than 0x7c00. This means with the above code added to the start of your bootsector, it would consistently print 0000 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM