Как связать два объектных файла, разместив их соответствующие разделы в разных местах? - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть программа начального загрузчика «boot.asm», которая должна содержать специальное слово со смещением 510 байт от начала.И у меня есть исходный код ядра, написанный на C "kernel.c".

Я планирую вызвать ядро ​​(которое будет во втором секторе hd), загрузив второй сектор жесткого диска из программы загрузчика.и поместите это в местоположение 0x8000 в памяти.

Теперь я компилирую оба исходных файла в объектные файлы ELF (отдельно) в «boot.o» и «kernel.o», а затем связываю их через компоновщик и выводю необработанный двоичный файл «kernel.bin».".

Я хочу поместить код моего загрузчика, начиная с 0x7c00, а затем в местоположение 0x7dfe, я должен добавить специальное слово.Затем прямо в 0x8000 я должен разместить свой код ядра.т.е. я хочу разместить соответствующие разделы обоих объектных файлов в разных местах.

Это моя неудачная попытка.

ENTRY(boot)
OUTPUT_FORMAT("binary")

SECTIONS{
  . = 0x7c00;
  .text :
  {
    *(.boot)
  }

  .sig : AT(0x7dfe){
     SHORT(0xaa55);
  }

  . = 0x8000;

  .text :
  {
    kernel.o(.text)
  }

  .rodata :
  {
    kernel.o(.rodata)
  }

  .data :
  {
    kernel.o(.data)
  }

  .bss :
  {
    kernel.o(.bss)
  }

}

Я понял, что исполняемый файл не может иметь раздел более одного раза.

У меня ограниченные знания о низком уровнепрограммирование.

Как мне решить эту проблему.Thankyou.

1 Ответ

0 голосов
/ 22 сентября 2018

Вам нужно исправить две вещи, не разбивать секцию вывода .text и использовать AT(), чтобы поместить ядро ​​сразу после загрузочного сектора в выходной двоичный файл, сохраняя его адрес 0x8000.Например, скрипт компоновщика должен работать примерно так:

ENTRY(boot)
OUTPUT_FORMAT("binary")

SECTIONS {
  . = 0x7c00;
  .boot :
  {
    *(.boot)
  }

  . = 0x7dfe;
  .sig : {
     SHORT(0xaa55);
  }

  . = 0x8000;
  .kernel : AT(0x7e00)  /* place immediately after the boot sector */
  {
    *(.text)
    *(.rodata)
    *(.data)
    _bss_start = .;
    *(.bss)
    *(COMMON)
    _bss_end = .;
  }
  kernel_sectors = (SIZEOF(.kernel) + 511) / 512;

  /DISCARD/ : {
        *(.eh_frame)
  }
}

Я добавил некоторые вещи для обработки разделов, которые вы увидите в скомпилированных объектных файлах GCC.Символы _bss_start и _bss_end могут использоваться для обнуления секции .bss, и согласно предложению Майкла Петча символ kernel_sector устанавливается на длину ядра в 512 байтовых секторах.

...