我不确定我做错了什么,但我已经尝试阅读有关调用GCC惯例的手册,并且没有发现任何有用的内容。我目前的问题是GCC为一个非常简单的操作生成了过多的代码,如下所示。
main.c中:
#ifdef __GNUC__
// defines for GCC
typedef void (* push1)(unsigned long);
#define PUSH1(P,A0)((push1)P)((unsigned long)A0)
#else
// defines for MSC
typedef void (__stdcall * push1)(unsigned long);
#define PUSH1(P,A0)((push1)P)((unsigned long)A0)
#endif
int main() {
// pointer to nasm-linked exit syscall "function".
// will not work for win32 target, provided as an example.
PUSH1(0x08048200,0x7F);
}
现在,让我们使用gcc构建并转储它:gcc -c main.c -Os;objdump -d main.o
:
main.o: file format elf32-i386
Disassembly of section .text:
00000000 <.text>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc pushl -0x4(%ecx)
a: b8 00 82 04 08 mov $0x8048200,%eax
f: 55 push %ebp
10: 89 e5 mov %esp,%ebp
12: 51 push %ecx
13: 83 ec 10 sub $0x10,%esp
16: 6a 7f push $0x7f
18: ff d0 call *%eax
1a: 8b 4d fc mov -0x4(%ebp),%ecx
1d: 83 c4 0c add $0xc,%esp
20: c9 leave
21: 8d 61 fc lea -0x4(%ecx),%esp
24: c3 ret
这是我能够获得的最小大小代码...如果我没有指定-O *或指定其他值,则它将是0x29 +字节长。
现在,让我们用ms c编译器v 6构建它(是的,98年iirc之一):wine /mnt/ssd/msc/6/cl /c /TC main.c;wine /mnt/ssd/msc/6/dumpbin /disasm main.obj
:
Dump of file main.obj
File Type: COFF OBJECT
_main:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 6A 7F push 7Fh
00000005: B8 00 82 04 08 mov eax,8048200h
0000000A: FF D0 call eax
0000000C: 5D pop ebp
0000000D: C3 ret
如何使GCC按大小代码生成类似的代码?任何提示,提示?你不同意结果代码应该小吗?为什么海湾合作委员会附加了这么多无用的代码?我认为在优化尺寸时,它比msc6这样的旧东西更聪明。我在这里缺少什么?
答案 0 :(得分:4)
main()在这里很特别:gcc正在做一些额外的工作,使堆栈在程序的入口点处对齐16字节。所以结果的大小不能直接比较...尝试将main()重命名为f(),你会看到gcc生成截然不同的代码。
(MSVC编译的代码不需要关心对齐,因为Windows对堆栈对齐有不同的规则。)
答案 1 :(得分:-1)
This是我能得到的最佳参考。我现在在Windows上,懒得登录我的Linux进行测试。这里(MinGW GCC 4.5.2),代码比你的小。一个区别是调用约定,stdcall当然比cdecl有一些字节优势(如果未指定,则默认使用GCC,或者使用-O1,我猜也是-Os),以清理堆栈。
这是我编译的方式和结果(源代码纯粹是从帖子中复制粘贴的)
gcc -S test.c:
_main:
pushl %ebp #
movl %esp, %ebp #,
andl $-16, %esp #,
subl $16, %esp #,
call ___main #
movl $127, (%esp) #,
movl $134513152, %eax #, tmp59
call *%eax # tmp59
leave
ret
gcc -c -o test.o test.c&amp;&amp; objdump -d test.o:
test.o: file format pe-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 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: c7 04 24 7f 00 00 00 movl $0x7f,(%esp)
15: b8 00 82 04 08 mov $0x8048200,%eax
1a: ff d0 call *%eax
1c: c9 leave
1d: c3 ret
1e: 90 nop
1f: 90 nop