0

It's easy to compile C source code into an executable: gcc hello.c -o hello. In contrast, this is how I am currently turning an assembly program into an executable:

cpp -P hello.S > hello.s  # Run preprocessor.
as hello.s -o hello.o  # Assemble.
ld hello.o -o hello  # Link.

Is there a way to do all of this using one command?

The OS is Debian 10.1 Buster running on a mipsel (32-bit MIPS little endian) machine.

For reference, this is hello.S, a MIPS assembly program that requires the use of the C preprocessor:

#include <regdef.h>
#include <sys/syscall.h>

.data
    mymsg: .asciiz "Hello\n"

.text
    .global __start

__start:
    li a0, 1
    la a1, mymsg
    li a2, 6
    li v0, SYS_write
    syscall
    li a0, 1
    li v0, SYS_exit
    syscall
Flux
  • 9,805
  • 5
  • 46
  • 92

2 Answers2

1

gcc -static -nostdlib hello.S runs it through CPP, then assembles it and links just that .o, no CRT start files and no libraries, not even libgcc.a.

-nostdlib is like -nostartfiles but leaves out libraries as well as CRT startup code. If I understand the docs correctly, -nostdlib is a combination of -nodefaultlibs -nostartfiles. https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

Modern Linux distros usually configure gcc with the default being -pie -fPIE. Using -static disables that (because PIE is a hack that uses an ELF "shared object" as an executable). (32-bit absolute addresses no longer allowed in x86-64 Linux?). Leaving -fPIE on doesn't matter if there are no .c or .cpp inputs, only assembler; it's a code-gen option.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • `gcc -static -nostdlib hello.S` produces an executable, but running the executable (`./a.out`) prints `Bus error` with an exit code of 138. – Flux Oct 04 '19 at 07:41
  • @Flux: So use a `strace ./a.out` and/or a debugger to find out what's wrong with your executable. Like maybe your `.data` section isn't aligned? Are you saying this executable is different from what you get by running `gcc -c hello.S` then `ld` manually? Use `gcc ... -v` to show what commands it ran. – Peter Cordes Oct 04 '19 at 09:16
-1

From the overal options part of the GCC documentation:

file.S
file.sx

Assembler code that must be preprocessed.

So the support for preprocessing, assembling and linking such source file is already supported.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • `gcc hello.S` results in an error `(.text+0x1c): undefined reference to \`main'` `collect2: error: ld returned 1 exit status`. Running `gcc hello.S -nostdlib` produces an executable, but running the executable prints garbage. My system's architecture is 32-bit MIPS in little endian mode. – Flux Oct 02 '19 at 10:37
  • @Flux Try `-nostdlib -nostartfiles`. – fuz Oct 02 '19 at 10:46
  • @fuz The resulting executable still prints garbage. – Flux Oct 02 '19 at 10:48
  • 1
    This doesn't answer the question. I was briefly fooled too into thinking just `gcc hello.S` would be the answer, but notice the `ld` command line that omits any libraries or CRT start files. That's the key part of the question. – Peter Cordes Oct 02 '19 at 11:02
  • @Flux: Are you sure Linux/ELF on MIPS still prepends symbols with a leading `_`? i.e. are you sure the C symbol `_start` really has the asm name `__start`? If your program is printing garbage, have you tried using a debugger? It sounds very weird that `-nostdlib` compiles without complaint but then doesn't work the same as manually running `ld`. Unless Linux/MIPS lets non-PIE-compatible code link into a PIE executable and then fail at runtime... Or whatever OS you have – Peter Cordes Oct 02 '19 at 11:06