I have some NASM files that generally have the structure:
[BITS 64] [ORG 0x0000000000200000] start: ... ret
I'm assembling them like so:
nasm -f bin abc.asm
I'd like to write some of these using GAS instead. Two questions:
What directives should I use in GAS? I've found the '.org' directive but GAS doesn't seem to have a '.bits' directive.
What should I pass to gcc
or as
to generate a plain binary file? I.e. what the -f bin
option does with NASM.
What directives should I use in GAS? I've found the '.org' directive but GAS doesn't seem to have a '.bits' directive.
The assembler defaults to 64--bit for me, you can use --32
or --64
to chose on the command line. Have a look at the manual for as to see how you can change the architecture inside the code if needed (e.g. .code16
can be used to generate real mode code for a boot loader).
You most likely don't want to use the .org
directive to specify where the code is located, but will probably want to use a link script or specify where the text and data segments are loaded on the command line. (org 0x0000000000200000
results in a 2+ MB binary file).
What should I pass to gcc or as to generate a plain binary file? I.e. what the -f bin option does with NASM.
$ cat test.S .section .text .globl _start _start: xor %rax, %rax mov test, %rax ret test: .quad 0x1234567812345678 $ as --64 -o test.o test.S $ ld -Ttext 200000 --oformat binary -o test.bin test.o
$ objdump -D -b binary -m i386:x86-64 test.bin test.bin: file format binary Disassembly of section .data:
0000000000000000 <.data>: 0: 48 31 c0 xor %rax,%rax 3: 48 8b 04 25 0c 00 20 mov 0x20000c,%rax a: 00 b: c3 retq
c: 78 56 js 0x64 e: 34 12 xor $0x12,%al 10: 78 56 js 0x68 12: 34 12 xor $0x12,%al
objcopy -O binary
A good option is:
as -o test.o test.S ld -Ttext 0x7C00 -o test.elf test.o objcopy -O binary kernel.elf kernel.bin
The advantage over ld --oformat binary
is that it is easier to use the symbols to debug via:
qemu-system-i386 -hda main.img -S -s & gdb main.elf -ex 'target remote localhost:1234'
See also: https://stackoverflow.com/a/32960272/895245
Linker script
-Ttext
is fine for quick and dirty testing, but for serious work you should use a script instead to increase robustness.
Otherwise, ld
will use a default script (ld --verbose
) intended for userland application, which does not look like your application.
Without further information, the minimal script I can give is:
SECTIONS { . = 2M; .text : { *(.*) } }
And then use it with -T
:
as --64 -o test.o test.S ld -T linker.ld --oformat binary -o test.bin test.o
But you will likely want to modify that script based on your exact application.
See also: Is there a way to get gcc to output raw binary?
I have a repository with working examples for some common use cases:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With