【问题标题】:gcc on windows generating garbage? windows vs linuxgcc 在 Windows 上产生垃圾? Windows 与 Linux
【发布时间】:2013-11-02 09:16:09
【问题描述】:

我试图找出为什么在 windows 中对同一程序的指令比 linux 多得多。 所以我只是在 C 中使用了int a=0xbeef;printf("test\n");,并在 Linux 和 Windows 中编译。当我调试和拆卸主机时,我得到了这个: 在 Linux 上:

0x080483e4 <+0>:     push   %ebp
0x080483e5 <+1>:     mov    %esp,%ebp
0x080483e7 <+3>:     and    $0xfffffff0,%esp
0x080483ea <+6>:     sub    $0x20,%esp
0x080483ed <+9>:     movl   $0xbeef,0x1c(%esp)
0x080483f5 <+17>:    movl   $0x80484d0,(%esp)
0x080483fc <+24>:    call   0x8048318 <puts@plt>
0x08048401 <+29>:    leave  
0x08048402 <+30>:    ret 

好的,这很好。我看到 esp 的 movl 0x1c 偏移量将值放在那里。

但在 Windows 中我得到了这个:

0x401290 <main>:        push   %ebp
0x401291 <main+1>:      mov    %esp,%ebp
0x401293 <main+3>:      sub    $0x18,%esp
0x401296 <main+6>:      and    $0xfffffff0,%esp
0x401299 <main+9>:      mov    $0x0,%eax
0x40129e <main+14>:     add    $0xf,%eax
0x4012a1 <main+17>:     add    $0xf,%eax
0x4012a4 <main+20>:     shr    $0x4,%eax
0x4012a7 <main+23>:     shl    $0x4,%eax
0x4012aa <main+26>:     mov    %eax,0xfffffff8(%ebp)
0x4012ad <main+29>:     mov    0xfffffff8(%ebp),%eax
0x4012b0 <main+32>:     call   0x401720 <_alloca>
0x4012b5 <main+37>:     call   0x4013c0 <__main>
0x4012ba <main+42>:     movl   $0xbeef,0xfffffffc(%ebp)
0x4012c1 <main+49>:     movl   $0x403000,(%esp,1)
0x4012c8 <main+56>:     call   0x401810 <printf>
0x4012cd <main+61>:     mov    $0x0,%eax
0x4012d2 <main+66>:     leave
0x4012d3 <main+67>:     ret

首先,我不知道为什么 windows 编译器 (mingw) 会生成这么多代码。是 Linux 的 2 倍……这让我思考。还有一件事:从 main+9 到 main+37 我看不到那段代码的意义。

如果有人回答这个问题我会很感激,我只是好奇:)

编辑: 在 linux 上使用 -O3 参数我得到了相同的结果,而在 Windows 中则发生了类似魔法的事情:

0x401290 <main>:        push   %ebp
0x401291 <main+1>:      mov    $0x10,%eax
0x401296 <main+6>:      mov    %esp,%ebp
0x401298 <main+8>:      sub    $0x8,%esp
0x40129b <main+11>:     and    $0xfffffff0,%esp
0x40129e <main+14>:     call   0x401700 <_alloca>
0x4012a3 <main+19>:     call   0x4013a0 <__main>
0x4012a8 <main+24>:     movl   $0x403000,(%esp,1)
0x4012af <main+31>:     call   0x4017f0 <puts>
0x4012b4 <main+36>:     leave
0x4012b5 <main+37>:     xor    %eax,%eax
0x4012b7 <main+39>:     ret

leave 然后 xor 然后 ret。好的 :D 调用 _alloca 和调用 __main 仍然存在。我不知道0x401291 &lt;main+1&gt;: mov $0x10,%eax 在这里做什么:D

【问题讨论】:

  • 哇。似乎 Windows 上的编译器正在控制 ALU。
  • 这只是样板 ABI 的东西,但是用 -O3 编译两者,它可能会缩小一点。
  • 类似怪异功能序言:stackoverflow.com/questions/3155257/…

标签: c linux windows assembly gdb


【解决方案1】:

你好像在用旧的3.x系列编译gcc,你最好升级一下。较新的版本不会调用alloca。我怀疑alloca 的特定版本可能使用寄存器约定,因此mov 0x10,%eax 可能正在为该调用设置参数。

__main 是在crtbegin.o 中定义的启动函数,它执行全局构造函数并使用atexit 注册一个将运行全局析构函数的函数。

还要注意main 得到特殊处理,如堆栈对齐代码和上述初始化。如果您只是对代码生成问题感兴趣,那么比较“普通”函数可能是个好主意。

【讨论】:

    【解决方案2】:

    有人注意到,在上面的例子中,编译器调用 puts,而在下面的例子中是 printf。我怀疑你在上面的例子中有优化,但在下面的例子中没有。

    它也可能是调试与非调试构建。

    【讨论】:

      猜你喜欢
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 2015-05-24
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      相关资源
      最近更新 更多