从C语言到汇编的转换

9

请问可以有人解释一下吗?我有一个C程序,我能转换成汇编吗?如果可以,怎么做呢?


我相信dev-cpp有选项(类似于gcc)可以生成汇编输出。我不知道dev-cpp是否具有用于中间输出的相同钩子,但我认为您并不真正需要这些来回答您的问题。 - Tim Post
此外,有关如何使 C 编译器的汇编输出更有趣的内容,请参考 如何从 GCC/clang 汇编输出中删除 "噪声"? - Peter Cordes
6个回答

23
如果您使用gcc,可以按照此页面的说明执行gcc -O2 -S -c foo.c来获取可读性更高的汇编输出。

页面还解释了如何获取源代码和生成的汇编代码 :-) +1 - garph0
1
@Anders Abel:如果我需要一些特殊的东西?例如PDP-11? - lego69
2
使用交叉编译器,生成您所需的架构的代码。 - Johan
4
为什么使用 -O2?你肯定希望没有优化,这样你可以理解这个东西。 - paxdiablo
gcc支持pdp-11,因此您应该能够使用它。 --target选项在这里应该很有用。 通常的目标语法是处理器格式,因此,假设您正在使用pdp-11的elf格式(这不太可能,但我对pdp-11可执行文件格式一无所知),您应该添加选项 --target pdp11-elf。 - garph0
显示剩余2条评论

5

使用gcc,您可以使用-S选项:

gcc -O2 -S myfile.c

大多数其他选项(例如-O2)也可以在此处使用,以确定产生何种类型的汇编代码。

然而,请注意,这只是暴露了编译器经过的一个中间步骤(不是生成汇编源文件,而是它所代表的机器代码)。将此代码通过汇编器传递后的最终结果与直接编译为机器代码没有任何区别。


3

这就是编译器的作用。

编译器将您的C程序编译为机器语言,这是机器程序的二进制表示。当人类想要编写机器语言时,他们会使用汇编语言编写它,然后将其翻译为二进制机器语言。

汇编代码只是二进制机器语言的可读形式。

C程序:

$ cat test.c 
#include <stdio.h>

int main(int argc, char **argv) {
    int a = 11+12;
    printf("a = %d\n", a);
    return 0;
}

编译它。
$ gcc -c test.c

将其拆开:

$ objdump -d test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 20                sub    $0x20,%esp
   9:   c7 44 24 1c 17 00 00    movl   $0x17,0x1c(%esp)
  10:   00 
  11:   b8 00 00 00 00          mov    $0x0,%eax
  16:   8b 54 24 1c             mov    0x1c(%esp),%edx
  1a:   89 54 24 04             mov    %edx,0x4(%esp)
  1e:   89 04 24                mov    %eax,(%esp)
  21:   e8 fc ff ff ff          call   22 <main+0x22>
  26:   b8 00 00 00 00          mov    $0x0,%eax
  2b:   c9                      leave  
  2c:   c3                      ret    

例如,我正在使用Dev-Cpp,我在哪里可以找到这个选项? - lego69
在项目的编译器/代码生成器选项中查找,搜索类似于“生成汇编清单”的内容。 - garph0

3

您的编译器应该有一些选项来实现这个功能。例如,对于gcc,您可以使用-S选项。以下是一个简短的示例:

// test.c

#include <stdio.h>

int
main ()
{
  printf ("hello, world\n");
  return 0;
}

使用-S选项进行编译。这将生成一个test.s文件,其中包含汇编代码:
.file   "test.c"
    .section    .rodata
.LC0:
    .string "hello, world"
    .text
.globl main
    .type   main, @function
main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $4, %esp
    movl    $.LC0, (%esp)
    call    puts
    movl    $0, %eax
    addl    $4, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

如果我需要特殊的东西?例如 PDP-11? - lego69

1
大多数编译器都有一些选项可以生成汇编清单,以及二进制文件。 在Visual Studio中,您可以在文件属性的“代码生成”部分找到它。
使用gcc时,您可以使用-S开关(大写S)
最后,如果您有一个二进制文件,您可以使用objdump -S(大写S)。

1

既然你提到了Dev-C ++,值得一提的是-S标志也可以在那里使用。假设在Windows上,Dev-C ++仍将命名输出为.exe,但结果不会是可执行文件,因此只需将扩展名更改为.txt或其他格式,以便可以在所选编辑器中读取。在“项目”>“项目选项”>“参数”>“编译器”或“工具”>“编译器选项”下添加选项/标志。


哈哈!好的!太棒了!我已经寻找这个大约半个小时,昨晚整晚都在找。终于找到了!我没有找到需要将其重命名为文档格式的地方!该死,我被愚弄了!非常感谢您先生! - bad_keypoints

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接