Запись / связывание плоского двоичного файла с использованием NASM + LD - PullRequest
6 голосов
/ 12 мая 2011

Я создаю свою собственную «игрушечную» операционную систему, и я дошел до того, что я пытаюсь понять связывающие и исполняемые форматы - в частности, у меня есть исполняемый файл двоичного формата плоских файлов, который я загружаю в память в адрес 0x500, а затем прямо позвонив. В качестве примера рассмотрим следующие две инструкции (я знаю, что они придуманы, я просто хотел включить и call и mov в мой образец)

mov ax, some_label
call some_label
; some_label is at address 0x99 into the resulting binary

До сих пор я использовал NASM для получения желаемого результата, используя директиву org 0x500 с командой nasm -f bin myfile.asm. Получившаяся разборка выглядит так и работает отлично:

mov ax, 0x599
call 0x599

Теперь я хочу начать использовать LD, чтобы связываться с другими объектами, но после долгих экспериментов и чтения я все еще не совсем понимаю, что происходит, чтобы получить надежные результаты.

Я понял, что для получения аналогичного результата мне нужно:

  • Получите NASM для вывода в формате obj, который включает в себя информацию о символах, подходящую для связывания (я выбрал ELF, так как формат кажется таким же хорошим, как и любой другой)
  • Получите LD, чтобы связать результат с адресом секции .text как 0x500, а затем выдать результат в виде плоского двоичного файла - это компоновщик, который в конечном итоге решает, к чему разрешаются различные смещения в конечном двоичном файле .

Пока что я пробовал следующее:

:: Output as ELF 
nasm -f elf myfile.asm
:: Then link and output as binary with the address of .text as 0x500
ld --oformat binary -Ttext 0x500 myfile.o

Однако это дает мне следующую ошибку (это на Mingw):

ld: невозможно выполнить операции PE с выходным файлом без PE

Поиск в Google привел меня к этому списку рассылки , что, кажется, имеет смысл, и поэтому вместо этого я попробовал следующее:

:: Output as ELF
nasm -f elf myfile.asm -o myfile.o
:: Link using LD
ld myfile.o -Ttext 0x500 -s -o myfile.tmp
:: Use objdump to output as a flat binary
objcopy -O binary myfile.tmp myfile

Однако полученный myfile выглядит как мусор:

00000000  66B8C105E8B8      mov eax,0xb8e805c1
00000006  0000              add [bx+si],al

Я пробовал несколько вариантов вышеупомянутого, но ни один из них не дает того, что я ожидал, и сейчас я совершенно сбит с толку:

  • Может кто-нибудь помочь мне понять, что здесь происходит?
  • И что мне делать, чтобы дать мне такой же контроль над тем, куда разрешаются адреса в полученном двоичном файле?

1 Ответ

3 голосов
/ 16 мая 2011

Итак, я выяснил, что я делал несколько неправильных вещей, наиболее серьезная из которых была попытка скомпилировать и связать 16-битный код с использованием LD (который не поддерживает 16-битный код) и без явного указания, что код является 16-битнымс использованием BITS 16 (что означало, что NASM выдавал 32-битные адреса памяти).

Это в целом объясняет некоторые странные сообщения об ошибках, которые LD выдаст мне в некоторых вариациях описанной выше ситуации, а также почемудизассемблирование связанного двоичного файла было мусором - я пытался декомпилировать 32-битный код как 16-битный код или наоборот.

В идеале я хотел бы иметь возможность связывать 16-битный код, но обнаружил, что яЯ не могу сделать это с LD (и есть очень мало альтернатив, которые может сделать это). Я решил согласиться с пониманием того, что происходит, когда я повторяю то же самое с 32-битным кодом.Мой входной файл:

; Address locations are now 32 bits so I must use `eax` instead of `ax`
mov eax, some_label 
call some_label
; some_label is at a different address into the resulting binary (because 
; pointers are wider the resulting machine code is larger)

Затем я связываю это, используя следующее:

:: Output as win32 object files - makes it possible to use -r with LD.
nasm -f win myfile.asm -o myfile.o
:: Link using LD - the -r flag prevents extra un-used code (e.g. __CTOR_LIST__) being generated - see the link in my original question text
ld myfile.o -Ttext 0x500 -s -r -o myfile.tmp
:: Use objdump to output as a flat binary - -j .text ensures that just the .text section is included which keeps the output file size down
objcopy -O binary -j .text myfile.tmp myfile

При разборке с использованием ndisasm Мне нужно указать -b 32, чтобы получить его правильноинтерпретировать код как 32-битный.

Потребовалось много экспериментов и прочтения неясных ссылок на форумах, но в результате я теперь все понимаю намного лучше.

...