0

The question is, "Is there an intuitive way to obtain/compile the NASM code from the source file?" (e.g., *.c to *.out binary file through NASM).


From my independent research (which I will include below), the answer I came to is "no", but I hoped to get more expert input.

As I cited a few StackOverflow posts in this question, many good links show how to obtain and compile, but they are either a bit old or for 32-bit (How to generate a nasm compilable assembly code from c source code on Linux?), and because my question is regarding specifically about the 64-bit NASM, I thought is not a possible duplicate.

At the moment, I am working on a project which involves assembly rewriting. I have a prototype working for the GAS assembly file.

However, I have heard from my colleagues that using the NASM assembly file (which I didn't know before) is better. After searching, I became convinced that NASM seems to be indeed a better assembly format if I were to consider multiple cases of my project (the second post gave me a good reason why I should try to pursue NASM):

To give a more precise example, the steps that are required for my assembly reassembling of GAS files are done without needing to do any extraneous modifications as the following steps:

gcc -save-temps -masm=intel main.c foo.c bar.c (this will generate a-*.s automatically)
python3 reassemble_asm.py --files=a-foo.s,a-main.s,a-bar.s
as *.s -o *.o
gcc *.o -o main.out

In contrast, for NASM though, to obtain the NASM in the first place, it needs to go through multiple processes as written here: Converting C to nasm assembly, and then afterward, it becomes even more tricky for 64-bit compilation as it seemingly requires numerous modification: Relocation error when compiling NASM code in 64-bit mode.

If I try to compile 64-bit of the example shown here: Converting C to nasm assembly,


// hello.c
#include <stdio.h>
int main()
{
printf( "Hello World \n" );
return 0;
}
gcc -fno-asynchronous-unwind-tables -fno-pie -no-pie -s -c -o hello.o hello.c
objconv -fnasm hello.o 
nasm -f elf64 hello.asm # this needs to be elf64, not elf
gcc hello.o -o hello
/usr/bin/ld: hello.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status


This will not work due to relocation issues, as I mentioned above. I tried doing many solutions I found (-fno-pie, default rel, etc...), but to no avail (this demo is not related to my question, just wanted to provide this example to make the question more complete).

From what I have gathered/searched, my gut feeling is that NASM is not intuitive in terms of generating/modifying/compiling the assembly file, and I need to stick with GAS. However, because of my lack of assembly language knowledge (as I didn't even know about the NASM until just now), I wanted to ensure I exhausted all of my options before making such a choice.

Furthermore, maybe there is still a way for me to use NASM that I have not thought of yet; hence I wanted to ask this question. Thank you in advance.

Jay
  • 373
  • 1
  • 10
  • 2
    If you are programmatically rewriting asm, I would stick to gnu assembler. The extra features of nasm don't matter and then you can use the C compiler output without problems. As for your example you need to add the `-no-pie` to the last linking step `gcc -no-pie hello.o -o hello` – Jester Jul 25 '23 at 18:40
  • @Jester thank you very much for your swift response. I have also tested your suggestion and it worked, so thank you very much! I used `no-pie` at the first step, but didn't realize I also needed to use it at the last step. – Jay Jul 25 '23 at 18:49
  • Looks like the only problem you ran into was asking GCC to make asm for a non-PIE (`-fno-pie`) but then trying to link the eventual NASM output into a PIE (`-fPIE -pie` is the default in most distros). [32-bit absolute addresses no longer allowed in x86-64 Linux?](https://stackoverflow.com/q/43367427) covers that. Is there anything here that isn't answered by a combination of that question and the GCC-to-NASM `objconv` Q&A you were following? – Peter Cordes Jul 25 '23 at 19:28
  • NASM has more helpful error messages in some cases where GAS's are misleading, so in general I'd recommend it. But for reading/modifying compiler output ([How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116)), use `gcc -O2 -S -masm=intel`. It's MASM-style not NASM, with GAS directives, and `mov edi, OFFSET symbol` or `lea rdi, [rip + symbol]` to put addresses in registers. – Peter Cordes Jul 25 '23 at 19:30
  • Hello, @PeterCordes; thank you for your response; I think I was able to find all the answers. Just a quick question, though, is there a particular reason why you also recommend (along with Jester) that I use MASM-style (this is already the style I'm using) to modify/reassemble the assembly file? As you stated, NASM has many more helpful messages and looks much cleaner after comparing both styles in-depth. – Jay Jul 25 '23 at 20:11
  • 1
    Just because GCC can generate it directly, with all the directives for data sections and so on. It avoids ever having to disassemble binaries back into source, instead directly editing asm text that's known-good and ready to assemble+link. If you want to make *significant* modifications and spend a lot of time trying different stuff with the asm source, then sure maybe worth turning it into NASM if you prefer that. (Also for Jester and myself, GAS's worse error messages aren't a problem because they at least include a line number, so we have the experience to just see what's wrong.) – Peter Cordes Jul 25 '23 at 20:37
  • 1
    Most of the hard stuff in asm isn't syntax for one line, it's putting together multiple instructions to do useful things. But I guess if you don't know the syntax for tricky stuff like NASM `call puts wrt ..plt` or `call [rel puts wrt ..got]` vs. GAS `call puts@plt` or `call [rip + puts@GOTPCREL]`, that's highly non-obvious... but those are things you can google on Stack Overflow. Or for GAS syntax, look at GCC output for examples. – Peter Cordes Jul 25 '23 at 20:42
  • I think my re-assembler will need to do a decent number of modifications + support larger applications (in my opinion, NASM seems to be very handy for this debugging in this case), so I am convinced I should spend a bit more time with the NASM before moving on. Thank you again @PeterCordes; your response was highly insightful and helpful. – Jay Jul 25 '23 at 21:03

0 Answers0