10

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 :)

9
  • 1
    Maybe you can start by writing your own assembler :) I'm guessing the "290" bytes you're referring to is from the file header: every binary object file has one of these. Commented Dec 12, 2011 at 22:53
  • @paulsm4: Yes! 290 bytes header but I dont want any header! Commented Dec 12, 2011 at 22:55
  • @Amir - can't you just use objcopy or segedit or something to copy out the binary parts you care about? Commented Dec 12, 2011 at 23:16
  • 1
    @CiroSantilli新疆改造中心996ICU六四事件: should this be closed as a duplicate of How to generate plain binaries like nasm -f bin with the GNU GAS assembler?? Commented Jul 15, 2019 at 2:41
  • @PeterCordes yes, that is what I said 5 years ago on my previous comment :-) Commented Jul 15, 2019 at 7:58

3 Answers 3

7

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.

Sign up to request clarification or add additional context in comments.

Comments

-1

Use NASM with the -f bin option to compile your assembly code to a raw binary file.

5 Comments

But NASM can't compile the assembly output of gcc (See gcc -S my_os.c -o my_os.asm -masm=intel)
On the other hand, gcc doesn't generate 16-bit code, which you need because your boot sector starts executing in 16-bit mode. All pointer/address manipulations in C code compiled for 32-bit mode will be wrong in 16-bit mode.
Downvoter, be more constructive.
@alex the poster is obviously using the GAS assembler, not NASM. So your answer is not really an answer at all.
@Hawken: IIRC, (g)as does not produce flat/raw binaries. Do we want an impossible solution?
-1
org 100h nop nop 

You can use fasm to compile:

fasm yourcode.asm targetfilename.com 

3 Comments

The question already says "When I compile it with NASM or FASM, output file length is 2 bytes". This isn't an answer to this question, which is about GAS.
I see, but I don't understand why must be use another compiler when fasm produce the correct result.
This was already debated in comments under the nasm -f bin answer (which is the same answer as this one). Presumably they want to use GAS syntax, not NASM or FASM, for whatever reason. Or it seems the question may have come from the mistaken impression that you could usefully use this with gcc -S output to make 16-bit code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.