23

Test platform is 32 bit Linux.

Basically, I know gcc can be used to generate both Intel and At&T style assembly code, but it seems that you can not directly use nasm/tasm to compile the Intel style assembly code gcc generated.

I am conducting a project analysis asm code on both windows and Linux platform, so I am thinking if they can be both compiled by platform independent assembler like nasm\yasm, I could have a much easier time...

So my question is how to generate a nasm compilable assembly code from c source code on Linux?

lllllllllllll
  • 6,731
  • 6
  • 28
  • 67
  • BTW, gcc / gas's `.intel_syntax` / `-masm=intel` syntax is MASM-like, not NASM. See https://stackoverflow.com/tags/intel-syntax/info. – Peter Cordes Nov 22 '17 at 05:48

3 Answers3

37

I find it's a better approach to disassemble the object files rather than use assembly code generated by gcc.

  1. First, generate an object file from your source code:

    gcc -fno-asynchronous-unwind-tables -O2 -s -c -o main.o main.c
    

    -fno-asynchronous-unwind-tables: do not generate unnecessary sections like .eh_frame

    -O2 optimizes so the asm isn't horrible. Optionally use -Os (size over speed) or -O3 (full optimization including auto-vectorization). Also you can tune for a CPU and and use extensions it supports with -march=native or -march=haswell or -march=znver1 (Zen)

    -s: make smaller executable (strip)

    -c -o main.o: compile but don't link, generate an object file called main.o

  2. Use objconv to generate nasm code:

    objconv -fnasm main.o
    

    The result will be stored in main.asm.

  3. The result will be very close to Nasm syntax. However you might need to make some minor tweaks to eliminiate warnings/errors. Simply try to compile it with Nasm

    nasm -f elf32 main.asm
    

    and fix the errors/warnings by hand. For example:

    • remove the align=N and execute/noexecute words from .SECTION lines.
    • remove the text : function from global declarations
    • remove the default rel line
    • remove empty sections if you wish etc
  4. Link the resulting main.o which generated by Nasm in step 3 using gcc:

    gcc main.o
    

    You can also link it using ld but it's much harder.

Peter Cordes
  • 245,674
  • 35
  • 423
  • 606
Babken Vardanyan
  • 10,432
  • 9
  • 55
  • 80
  • 1
    You should probably use `gcc -O2` at least to optimize, unless you specifically want an inefficient bloated executable with asm you don't want to look at. – Peter Cordes Nov 22 '17 at 05:50
10

If you're lazy: https://github.com/diogovk/c2nasm

There I have a script that does Babken Vardanyan's suggestion automatically.

diogovk
  • 1,846
  • 16
  • 21
  • You should enable at least `gcc -O2` by default. Why would anyone ever want un-optimized code, especially if you're not converting the debug-info? – Peter Cordes Nov 22 '17 at 05:51
  • 5
    Most of the code being compiled with this tool is for purely didactic purposes. If the compiler optimizes, it might take "shortcuts" that might confuse the students, no? In that sense being more verbose is not a bad thing. – diogovk Nov 23 '17 at 19:24
  • IMO the output for `int add ( int a, int b ) { return a+b; }` makes a lot more sense (i.e. what I'd do by hand) with `-O2` than with `-O0` (https://godbolt.org/g/6cAehf). See https://stackoverflow.com/questions/38552116/how-to-remove-noise-from-gcc-clang-assembly-output (especially the link to Matt Godbolt's talk). The trick is to write functions that take args and return values, instead of a `main()` that optimizes away to printing and/or returning a constant. – Peter Cordes Nov 23 '17 at 21:06
  • Storing / reloading everything to memory between every C statement (to support debugger modification or jumping) makes it harder to follow, unless you look at the compiler asm output with `-fverbose-asm` to have it keep track of the C vars for you. – Peter Cordes Nov 23 '17 at 21:09
  • Anyway, yes, you have a point about `-O2` maybe being too much. `-O1` or `-Og` can be better choices for beginners. But Stack Overflow gets questions like "why does the compiler use extra stack space" or waste instructions asking about `-O0` output. – Peter Cordes Nov 23 '17 at 21:10
0

Heres a way to do it without objconv

ndisasm -u <(objdump -j .text -d main.o | cut -d: -f2 | cut -d$'\t' -f 2 | perl -ne 'next if /file/; s/\s+//g; print' | xxd -r -p)
skyfire
  • 143
  • 6