Я сейчас пытаюсь собрать двухэтапный загрузчик в ассемблере GNU. Я использую команду as
для компиляции файлов сборки и команду ld
, чтобы связать их с конечным двоичным файлом. Некоторая информация заранее:
$ as --version
GNU assembler (GNU Binutils for Debian) 2.28 [...]
This assembler was configured for a target of `x86_64-linux-gnu'
А ld
:
$ ld --version
GNU ld (GNU Binutils for Debian) 2.28 [...]
Уязвимый файл сборки:
.code16
.section .test
label: .short 0x1234
.section .text
.global _setup32
_setup32:
cli
xor %ax, %ax
# Some more code [...]
И скрипт компоновщика, используемый для создания двоичного файла: Прежде чем кто-либо спросит, следующий скрипт компоновщика является частью второго этапа моего загрузчика, отсюда и происхождение 0x8000
.
OUTPUT_FORMAT(binary)
ENTRY(_setup32)
SECTIONS
{
. = 0x8000;
_SETUP_START = .;
.test ALIGN(0x10) : {
*(.test*)
}
.text ALIGN(0x10) : {
_TEXT_START = .;
*(.text*)
_TEXT_END = .;
}
.rodata ALIGN(0x10) : {
_RODATA_START = .;
*(.rodata*)
_RODATA_END = .;
}
.data ALIGN(0x10) : {
_DATA_START = .;
*(.data*)
_DATA_END = .;
}
.bss ALIGN(0x10) : {
_BSS_START = .;
*(.bss*)
_BSS_END = .;
}
/DISCARD/ : {
*(.comment*)
}
_SETUP_END = .;
}
Однако после того, как окончательный файл setup.bin
был создан, значение 0x1234
не находится в начале hexdump. На самом деле, он даже не включен в окончательный вариант. Загрузчик работает абсолютно нормально, я просто не могу назначить переменные или вообще байты отдельным разделам.
Я использую следующие, очень простые правила в моем Makefile:
$(SETUPBIN): $(SETUP).o
$(LD) -T setup.ld $(SETUP).o -o $@
%.o: %.asm
$(AS) $< -o $@
Более того: я знаю о директивах GNU AS .text
и .data
, но они хранят инструкции и байты только в фиксированных местах двоичного файла: все в директиве .text
находится в начале двоичного файла, тогда как все в .data
находится в конце двоичного файла.
Как мне все поместить в пользовательский раздел?