Вы не предоставляете минимальный полный проверяемый пример, показывающий загрузчик и как его получить в VDI. Но, как минимум, вам нужно разместить 0xAA55 в последних двух байтах основной загрузочной записи. В приведенном ниже примере создается простой загрузчик; создает исходное изображение 2MiB; помещает загрузчик в необработанное изображение; и преобразует необработанное изображение в VDI.
boot.asm
:
BITS 16
ORG 0x7C00
xor ax, ax
mov ds, ax
mov ss, ax ; Stack below bootloader
mov sp, 0x7c00
mov ax, 0xb800 ; Video segment b800
mov es, ax
; Print Hello with white on light magenta
mov word [es:0x0], 0x57 << 8 | 'H'
mov word [es:0x2], 0x57 << 8 | 'e'
mov word [es:0x4], 0x57 << 8 | 'l'
mov word [es:0x6], 0x57 << 8 | 'l'
mov word [es:0x8], 0x57 << 8 | 'o'
; End with infinite loop
cli
endloop:
hlt
jmp endloop
; Fill out to 510 bytes and add boot signature
times 510 - ($ - $$) db 0
dw 0xAA55 ; add boot signature at the end of bootloader
Затем я использую эту команду для создания файла загрузчика boot.bin
:
nasm -f bin boot.asm -o boot.bin
Создайте файл образа диска 2MiB 1.raw
:
dd if=/dev/zero of=1.raw bs=1024 count=2048
Поместите загрузчик boot.bin
в начало файла 1.raw
, не обрезая остальную часть файла:
dd if=boot.bin of=1.raw conv=notrunc
Создайте изображение VDI с именем 1.vdi
из 1.raw
:
rm -f 1.vdi
VBoxManage convertfromraw 1.raw 1.vdi --format VDI
При добавлении в виртуальную машину в VirtualBox я получаю это на дисплее:
В прилагаемом файле изображения 1.vdi
я заметил это, когда сделал hexdump
:
00200000 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55
*
002004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
00300000
blockquote>
Этот вывод подсказывает мне, что вы отменили байты начальной загрузки в вашем файле. Он должен быть 0x55, за которым следует 0xaa. 0xaa55 как WORD хранится с байтами, которые были отменены.
Допустимый загрузочный носитель может быть больше, чем правильное получение начальной подписи. Некоторые BIOS могут искать определенные инструкции в первых байтах, которые обычно находятся в загрузчиках. Несоблюдение таких инструкций (примеры часто включают такие вещи, как JMP , XOR , CLI , MOV ) могут привести к его думать, что это не допустимый загрузочный носитель.
Один из способов проверить, достаточно ли 0xAA55 в конце, я использовал hexedit и изменил ваш файл 1.vdi
, чтобы выглядеть так:
blockquote>00200000 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 00200010 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 * 002001f0 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 55 aa <-- Corrected signature at 1fe & 1ff 00200200 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 * 002004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 00300000
Выполнение этого изменения не помогло. Затем я использовал hexedit и поместил код операции CLI (0xFA) в качестве первого байта сектора. Результирующий файл теперь выглядит следующим образом:
blockquote>v-- CLI instruction 00200000 fa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 00200010 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 * 002001f0 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 55 aa 00200200 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 aa 55 * 002004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 00300000
Я поместил
fa
в качестве первого байта в загрузчик. Теперь, когда я использую ваше изображение, ошибка Не найден загрузочный носитель! Системная остановка больше не отображается. Это говорит о том, что VirtualBox ищет больше, чем загрузочную подпись, и делает какую-то проверку здравомыслия, чтобы определить, является ли начало загрузчика исполняемыми инструкциями. Это не редкость для BIOS. Некоторые могут сделать такую проверку, а некоторые - нет. В это время я не просматривал исходный код VirtualBox, чтобы определить точные проверки, которые он выполняет, чтобы определить его.
Когда t
используется само по себе в выражении, происходит преобразование между массивами и указателями, это создает указатель на первый элемент массива.
Когда t
является используется как аргумент оператора &
, такое преобразование не происходит. &
затем явно принимает адрес t
(массив). &t
является указателем на массив в целом.
Первый элемент массива находится в той же позиции в памяти, что и начало всего массива, и поэтому эти два указателя имеют одинаковое значение .
Фактическим типом t
является int[10]
, поэтому &t
является адресом массива. Кроме того, int[]
неявно преобразуется в int*
, поэтому t
преобразует в адрес массива как первый элемент массива.
Нет переменной под названием t
, так как вы не можете ее изменить. Имя t
просто ссылается на адрес первого элемента (а также имеет связанный с ним размер). Таким образом, обращение адреса адреса на самом деле не имеет смысла, а C «сворачивает» его на просто адрес.
То же самое происходит для случая функций:
int foo(void)
{
return 12;
}
printf("%p and %p\n", (void *) foo, (void *) &foo);
Это должно печатать одно и то же, поскольку нет переменной, удерживающей адрес foo
, адрес которого по очереди можно взять.
t
. Вы можете передать его функции, которая принимает аргумент с типом int(&)[10]
.
– Abyx
7 December 2011 в 11:10
u
, являющееся указателем. – quuxbazer 7 December 2011 в 11:33u
есть i> указатель.t
является i> массивом.int * u = t
применяет преобразование массива к указателю вt
и инициализируетu
с результатом. – Mankarse 7 December 2011 в 11:45(e ? a : n)
не создает указатель, если, например, обе стороны имеют один и тот же тип массива. – Johannes Schaub - litb 7 December 2011 в 12:46