Как скомпилировать файл сборки в необработанный двоичный формат (например, DOS .com) с помощью ассемблера GNU (as)?

Я хочу скомпилировать этот исходный код в Windows (это просто пример):

start:
NOP
NOP

Когда я компилирую его с помощью NASM или FASM, длина выходного файла составляет 2 байта. Но когда я компилирую его с помощью ассемблера GNU (as), длина выходного файла составляет 292 байта!

Как скомпилировать файл сборки в необработанный двоичный формат (например, DOS .com) с помощью ассемблера GNU (as)?


Почему я это делаю?

Я хочу написать свою собственную простую ОС, я пишу свои коды на C (без использования каких-либо стандартных библиотек C, даже stdio.h или math.h) и конвертирую их в сборку:

gcc -S my_os.c -o my_os.asm -masm=intel

Затем я компилирую файл сборки в необработанный двоичный файл:

as my_os.asm

Затем я переименовываю a.out (вывод ассемблера) в my_os.flp и, наконец, запускаю свою ОС с VMWare :)


person Amir Saniyan    schedule 12.12.2011    source источник
comment
Может быть, вы можете начать с написания собственного ассемблера :) Я предполагаю, что 290 байт, о которых вы говорите, взяты из заголовка файла: каждый двоичный объектный файл имеет один из них.   -  person paulsm4    schedule 13.12.2011
comment
@paulsm4: Да! Заголовок 290 байт, но мне не нужен заголовок!   -  person Amir Saniyan    schedule 13.12.2011
comment
@Amir, разве вы не можете просто использовать objcopy или segedit или что-то еще, чтобы скопировать нужные вам двоичные части?   -  person Carl Norum    schedule 13.12.2011
comment
@PeterCordes да, это то, что я сказал 5 лет назад в своем предыдущем комментарии :-)   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 15.07.2019
comment
@CiroSantilli新疆改造中心996ICU六四事件: Я спрашивал, верно ли это, поскольку у вас есть ответы на оба вопроса, которые вы обновили с тех пор.   -  person Peter Cordes    schedule 15.07.2019
comment
@PeterCordes Мне нужен один из этих сборочных молотков XD   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 15.07.2019
comment
@CiroSantilli新疆改造中心996ICU六四事件: Некоторые из ваших ответов на сборку, похоже, относятся ко второй учетной записи. Их объединение может помочь.   -  person Peter Cordes    schedule 15.07.2019
comment
@PeterCordes все в порядке, мне нужна политически аморальная марионетка по причинам :-)   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 15.07.2019


Ответы (3)


ld --oformat binary

Для быстрых и грязных тестов вы можете сделать:

as -o a.o a.S
ld --oformat binary -o a.out a.o
hd a.out

Дает:

00000000  90 90                                             |..|
00000002

К сожалению, это дает предупреждение:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400000

что не имеет большого смысла с binary. Его можно заглушить с помощью:

.section .text
.globl start
start:
nop
nop

и:

ld -e start --oformat binary -o a.out a.o

или просто с:

ld -e 0 --oformat binary -o a.out a.o

который сообщает ld, что точка входа не _start, а код по адресу 0.

Обидно, что ни as, ни ld не могут принимать ввод/вывод из stdin/stdout, так что никакой пайпинг.

Правильный загрузочный сектор

Если вы собираетесь заняться чем-то более серьезным, лучший способ — сгенерировать чистый минимальный скрипт компоновщика. linker.ld:

SECTIONS
{
    . = 0x7c00;
    .text :
    {
        *(.*)
        . = 0x1FE;
        SHORT(0xAA55)
    }
}

Здесь же размещаем магические байты со скриптом компоновщика.

Сценарий компоновщика важен, прежде всего, для управления выходными адресами после перемещения. Узнайте больше о перемещении по адресу: https://stackoverflow.com/a/30507725/895245.

Используйте его как:

as -o a.o a.S
ld --oformat binary -o a.img -T linker.ld a.o

И тогда вы можете загрузиться как:

qemu-system-i386 -hda a.img

Рабочие примеры в этом репозитории: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d217b180be4220a0b4a453f31275d38e697a99e0/Makefile

Протестировано на Binutils 2.24, Ubuntu 14.04.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 26.08.2015

Используйте NASM с параметром -f bin, чтобы скомпилировать ваш ассемблерный код в необработанный двоичный файл.

person Alexey Frunze    schedule 12.12.2011
comment
Но NASM не может скомпилировать вывод сборки gcc (см. gcc -S my_os.c -o my_os.asm -masm=intel) - person Amir Saniyan; 13.12.2011
comment
С другой стороны, gcc не генерирует 16-битный код, который вам нужен, потому что ваш загрузочный сектор начинает выполняться в 16-битном режиме. Все манипуляции с указателем/адресом в коде C, скомпилированном для 32-битного режима, будут неправильными в 16-битном режиме. - person Alexey Frunze; 13.12.2011
comment
Downvoter, будьте более конструктивны. - person Alexey Frunze; 13.12.2011
comment
@alex плакат явно использует ассемблер GAS, а не NASM. Так что ваш ответ на самом деле не ответ вообще. - person Hawken; 23.04.2012
comment
@Hawken: IIRC, (g)as не создает плоские/необработанные двоичные файлы. Хотим ли мы невозможного решения? - person Alexey Frunze; 23.04.2012

org 100h
nop
nop

Вы можете использовать fasm для компиляции:

fasm yourcode.asm targetfilename.com
person sarkiroka    schedule 22.06.2018
comment
В вопросе уже говорится: Когда я компилирую его с помощью NASM или FASM, длина выходного файла составляет 2 байта. Это не ответ на этот вопрос о GAS. - person Peter Cordes; 22.06.2018
comment
Понятно, но я не понимаю, зачем использовать другой компилятор, когда fasm выдает правильный результат. - person sarkiroka; 22.06.2018
comment
Это уже было обсуждается в комментариях под ответом nasm -f bin (это тот же ответ, что и этот). Предположительно, по какой-то причине они хотят использовать синтаксис GAS, а не NASM или FASM. Или кажется, что вопрос мог возникнуть из-за ошибочного впечатления, что вы могли бы с пользой использовать это с выводом gcc -S для создания 16-битного кода. - person Peter Cordes; 22.06.2018