Can gcc compile x86 assembly or just link it?

42,728

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
Share:
42,728

Related videos on Youtube

Niklas Rosencrantz
Author by

Niklas Rosencrantz

I'm as simple as possible but not any simpler.

Updated on September 08, 2021

Comments

  • Niklas Rosencrantz
    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 files

    gcc -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
      cnicutar about 11 years
      Yes, that's exactly what as(1) does.
    • Peter Cordes
      Peter Cordes almost 8 years
      See also this Q&A on how to assemble and link using gcc, for programs that define _start or main, with/without libc.
  • Niklas Rosencrantz
    Niklas Rosencrantz about 11 years
    But 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 to main' Thank you for the answer.
  • Dietrich Epp
    Dietrich Epp about 11 years
    That'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 be main.
  • Niklas Rosencrantz
    Niklas Rosencrantz about 11 years
    Thanks. 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 the as program might also compile it but in this case I could use gcc with a simple hello world program to compile and run x86 assembly.
  • Cody Gray
    Cody Gray almost 8 years
    Unlikely 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
    Peter Cordes over 2 years
    Some 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. With gcc -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