测试平台为32位Linux。
基本上,我知道gcc可以用来生成Intel和At&T风格的汇编代码,但似乎你不能直接使用nasm/tasm来编译gcc生成的Intel风格的汇编代码。
我正在进行一个项目分析,需要在Windows和Linux平台上分析汇编代码,所以我想知道它们是否都可以通过像nasm\yasm这样的平台无关汇编器来编译,这样我就可以更轻松地工作了...
所以我的问题是如何从c源代码在Linux上生成可编译的nasm汇编代码?
测试平台为32位Linux。
基本上,我知道gcc可以用来生成Intel和At&T风格的汇编代码,但似乎你不能直接使用nasm/tasm来编译gcc生成的Intel风格的汇编代码。
我正在进行一个项目分析,需要在Windows和Linux平台上分析汇编代码,所以我想知道它们是否都可以通过像nasm\yasm这样的平台无关汇编器来编译,这样我就可以更轻松地工作了...
所以我的问题是如何从c源代码在Linux上生成可编译的nasm汇编代码?
我认为将目标文件进行反汇编比使用由gcc生成的汇编代码更好。
首先,从您的源代码生成一个目标文件:
gcc -fno-asynchronous-unwind-tables -O2 -s -c -o main.o main.c
-fno-asynchronous-unwind-tables
:不生成不必要的段,如.eh_frame
-O2
:优化汇编代码以避免可怕的性能。可以选择使用-Os
(减小体积而牺牲速度)或-O3
(包括自动向量化在内的完全优化)。还可以通过-march=native
、-march=haswell
或-march=znver1
(Zen)来为 CPU 进行调整并使用它支持的扩展。
-s
:生成较小的可执行文件(strip)
-c -o main.o
:编译但不链接,生成名为main.o
的目标文件
使用objconv生成nasm
代码:
objconv -fnasm main.o
结果将被存储在main.asm
中。
结果将非常接近Nasm语法。然而,您可能需要进行一些微小的调整以消除警告/错误。只需尝试使用Nasm编译它即可。
nasm -f elf32 main.asm
通过手动修复错误/警告来解决问题。例如:
.SECTION
行中删除align=N
和execute
/noexecute
单词。global
声明中删除文本: function
default rel
行使用gcc链接步骤3中由Nasm生成的main.o
文件:
gcc main.o
你也可以使用ld来链接它,但这更困难。
gcc -O2
进行优化,除非你特别想要一个效率低下、臃肿的可执行文件和你不想看到的汇编代码。 - Peter Cordes-fno-pie
/ -no-pie
是一个对于32位代码来说简化对全局变量和其他静态存储的访问非常不错的主意,除非您真的想将结果链接回到32位PIE。对于64位代码,使用nasm -felf64
,RIP相对寻址是廉价且高效的。(所以保留default rel
行)。 - Peter Cordesgcc -O2
。为什么有人会想要未经优化的代码,特别是如果您没有转换调试信息? - Peter Cordes-O2
编译选项编译int add(int a, int b) { return a+b; }
函数的输出结果更有意义(即手动计算得到的结果),而不是使用-O0
(https://godbolt.org/g/6cAehf)。请参考https://dev59.com/n1kT5IYBdhLWcg3wefUn(特别是Matt Godbolt的演讲链接)。关键是编写接受参数并返回值的函数,而不是一个被优化为打印和/或返回常量的main()
函数。 - Peter Cordes-fverbose-asm
查看编译器汇编输出以让其为您跟踪C变量。 - Peter Cordesobjconv
的方法。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)
.intel_syntax
/-masm=intel
语法类似于 MASM,而不是 NASM。请参见 https://stackoverflow.com/tags/intel-syntax/info。 - Peter Cordes