c - Windows 上的 gcc 会产生垃圾吗? Windows 与 Linux

标签 c linux windows assembly mingw

我试图找出为什么同一程序在 Windows 中的指令比在 Linux 中多得多。 所以我就用了 int a=0xbeef;printf("test\n");用 C 编写并在 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

离开然后异或然后ret。好的:D 调用 _alloca 和调用 __main 仍然存在。我不知道什么是 0x401291 <main+1>: mov $0x10,%eax在这里做:D

最佳答案

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

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

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

关于c - Windows 上的 gcc 会产生垃圾吗? Windows 与 Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19552816/

相关文章:

c - 编程指针问题

c - 将登录信息与套接字相关联?

c++ - 确定两个文件路径引用同一个文件对象的最佳方法是什么?

Linux dlopen : can a library be "notified" when it is loaded?

java - Tomcat 8 : Wrong interpretation of message "java.util.Arrays.stream(Unknown Source)"

c - 非法内存写入导致 recv() 返回零

linux - 按修改日期查找和排序文件

php - 在多个文件中有条件地替换 XML 标签

windows - 在 Windows 上读取原始 USB 输入

.net - 在没有 OpenOffice 自动化的情况下将 SXW 转换为 PDF