Can gcc compile x86 assembly or just link it?
Solution 1
You're already doing it.
gcc -c asm_functions.S
That step produces an object file, asm_functions.o
. The object file is "linkable" (as opposed to "loadable") file that contains the machine code, with some extra instructions for how the linker should modify the code when linking. The gcc
program itself is just a driver, it runs as
behind the scenes for you to produce asm_functions.o
. So you do have the option of running as
directly, but often it's easier to run the gcc
frontend.
Solution 2
Although the update works, the original code could have been compiled by simply using gcc -nostdlib
. For example,
gcc -nostdlib 32.s -o 32
Related videos on Youtube
Niklas Rosencrantz
I'm as simple as possible but not any simpler.
Updated on September 08, 2021Comments
-
Niklas Rosencrantz over 2 years
gcc can produce assembly but how do I compile pure assembly with gcc or other compiler? I know x86 assembly is difficult and another instruction set than the MIPS and Nios I was looking at but now I want to try to compile direct x86 asm. There are instruction for how to do it but there's a C file included and I don't need a C file for my first most basic compile.
gcc -o test_asm asm_functions.S test_asm.c
There's the step creating
.o
filesgcc -c asm_functions.S gcc -c test_asm.c gcc -o test_asm asm_functions.o test_asm.o
But I don't see the step where I can directly compile x86 asm with gcc. There's another program named GNU as (GNU Assembler), can it be used to translate x86 assembly to machine code?
Test
Code (32.s)
.globl _start .text _start: movl $len, %edx movl $msg, %ecx movl $1, %ebx movl $4, %eax int $0x80 movl $0, %ebx movl $1, %eax int $0x80 .data msg: .ascii "Hello, world!\n" len = . - msg
Steps
$ gcc -c 32.s $ ls 32* 32.o 32.s $ gcc -o 32 32.o 32.o: In function `_start': (.text+0x0): multiple definition of `_start' /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20): undefined reference to `main'
So it seems it may have mixed 32 and 64 bits, must I tell the complier whether the assembly is 32 or 64 bit instructions?
Update
This test worked with gcc.
$ cat hello.s .data .globl hello hello: .string "Hi World\n" .text .global main main: pushq %rbp movq %rsp, %rbp movq $hello, %rdi call puts movq $0, %rax leave ret $ gcc hello.s -o hello $ ./hello Hi World
-
cnicutar about 11 yearsYes, that's exactly what
as(1)
does. -
Peter Cordes almost 8 yearsSee also this Q&A on how to assemble and link using gcc, for programs that define
_start
ormain
, with/without libc.
-
-
Niklas Rosencrantz about 11 yearsBut when I try to link just an object file created from pure assembly I get an error message I can't understand (
In function
_start': (.text+0x0): multiple definition of_start' /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function
_start': (.text+0x20): undefined reference tomain'
Thank you for the answer. -
Dietrich Epp about 11 yearsThat's a linking problem, not a compiling problem! If you use
gcc
to link, you get the C runtime by default, and your entry point should bemain
. -
Niklas Rosencrantz about 11 yearsThanks. It works (
gcc hello.s -o hello
) to compile and run to x86 assembly now. I updated the question with the code and cmd I use. I didn't try whether this code is spec to linux, it may be other assembly for other operating systems and theas
program might also compile it but in this case I could usegcc
with a simple hello world program to compile and run x86 assembly. -
Cody Gray almost 8 yearsUnlikely that passing your name as a parameter would have much effect. And what's that random 32? Using line breaks and code formatting would make your answer much more readable.
-
Peter Cordes over 2 yearsSome code will also benefit from (or require)
-no-pie
on modern distros. no-pie used to be the default, but isn't anymore in most modern GNU/Linux distro GCC configs. Especially for 64-bit code using absolute addresses. Withgcc -m32 -nostdlib foo.S
, it may still work to build a PIE, but if you do link libc then you need puts@plt or manual -fno-plt asm;see Can't call C standard library function on 64-bit Linux from assembly (yasm) code