2

I'm trying to find out why in windows has so much more instructions for the same program than linux. So I just used int a=0xbeef; and printf("test\n"); in C and compiled in Linux and Windows. When I debug and disassembly the main frame I got this: On 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 

Ok that's nice. I see the movl 0x1c offset of esp to put the value there.

But in windows I got this:

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

First of all, I don't know why the windows compiler (mingw) generate so much code. Is 2x more than Linux... this makes me thinking. And another thing: from main+9 to main+37 I can't see the point of that code.

I would thank if someone answer to this, I'm just curious :)

edit: With -O3 argument on linux I got the same and in windows something like magic happends:

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 then xor then ret. ok :D the call _alloca and call __main still there. and I don't know what is 0x401291 <main+1>: mov $0x10,%eax doing here :D

4

2 回答 2

4

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

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

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

于 2013-10-23T23:08:35.487 回答
0

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

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

于 2013-10-23T21:48:56.080 回答