I want to compile this source code in Windows (It just an example):
start:
NOP
NOP
When I compile it with NASM or FASM, output file length is 2 bytes. But when I compile it with GNU assembler (as) the output file length is 292 bytes!
How to compile an assembly file to a raw binary (like DOS .com) format with GNU assembler (as)?
Why I do this?
I want to write my own simple OS, I write my codes with C (without using any C standard libraries even stdio.h or math.h) and convert it to assembly:
gcc -S my_os.c -o my_os.asm -masm=intel
Then, I compile assembly file to a raw binary:
as my_os.asm
Then I rename a.out
(output of assembler) to my_os.flp
and finally start my OS with VMWare :)
ld --oformat binary
For quick and dirty tests you can do:
as -o a.o a.S
ld --oformat binary -o a.out a.o
hd a.out
Gives:
00000000 90 90 |..|
00000002
Unfortunately this gives a warning:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400000
which does not make much sense with binary
. It could be silenced with:
.section .text
.globl start
start:
nop
nop
and:
ld -e start --oformat binary -o a.out a.o
or simply with:
ld -e 0 --oformat binary -o a.out a.o
which tells ld
that the entry point is not _start
but the code at address 0
.
It is a shame that neither as
nor ld
can take input / ouptut from stdin / stdout, so no piping.
Proper boot sector
If you are going to to something more serious, the best method is to generate a clean minimal linker script. linker.ld
:
SECTIONS
{
. = 0x7c00;
.text :
{
*(.*)
. = 0x1FE;
SHORT(0xAA55)
}
}
Here we also place the magic bytes with the linker script.
The linker script is important above all to control the output addresses after relocation. Learn more about relocation at: https://stackoverflow.com/a/30507725/895245
Use it as:
as -o a.o a.S
ld --oformat binary -o a.img -T linker.ld a.o
And then you can boot as:
qemu-system-i386 -hda a.img
Working examples on this repository: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d217b180be4220a0b4a453f31275d38e697a99e0/Makefile
Tested on Binutils 2.24, Ubuntu 14.04.