2013 在w7 32位系统下把c文件汇编后,确实与mac后的差异很大。可不仅仅是寄存器eax与rax的区别。我想说的是函数参数传递的不同 mac下clang编译后函数的参数先保存在寄存器中(以一定的规则保存),然后在函数中压入栈里, 复制代码 代码如下: .global _decToBin _decToBin: pushq %rbp movq %rsp,%rbp movq %rdi,-8(%rbp) #第一个参数,保存在rdi中 movq %rsi,-16(%rbp) #第二个参数,保存在rsi中 movq -8(%rbp),%rax movq -16(%rbp),%rbx movq $63,%rcx ...... popq %rbp ret 而我在w7下使用cygwin安装的gcc编译test.c文件: test.c: 复制代码 代码如下: int hello(int a,int b,int c,int d) { return b; } test.c 复制代码 代码如下: .file "test.c" .text .globl _hello .def _hello; .scl 2; .type 32; .endef _hello: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax #说明参数是函数在使用其值之前就已经压入栈中 popl %ebp ret 这说明clang与gcc使用了两种不同的规则(网上有很多介绍函数值传递的不同规则的,我就不介绍了)。 所以不同的平台不同的编译器要不同的对待。以上算是上次的不足补充吧。 下面来看看数组: test.c例子: 复制代码 代码如下: void hello1() { int a[3]={1,2,3}; int b=a[1]; } void hello2() { int a[3]={1,2,3}; int b=*(a+1); } void hello3() { int a[3]={1,2,3}; int b=1[a]; //这也对? } 如果看的够仔细的话,三个函数没什么不同就是对数组a[1]的不同(当然函数名除外). gcc -S test.c 后: 复制代码 代码如下: .file "test.c" .data .align 4 LC0: .long 1 .long 2 .long 3 .text .globl _hello1 .def _hello1; .scl 2; .type 32; .endef _hello1: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx subl $16, %esp leal -28(%ebp), %edx movl $LC0, %ebx movl $3, %eax movl %edx, %edi movl %ebx, %esi movl %eax, %ecx rep movsl movl -24(%ebp), %eax movl %eax, -16(%ebp) addl $16, %esp popl %ebx popl %esi popl %edi popl %ebp ret .globl _hello2 .def _hello2; .scl 2; .type 32; .endef _hello2: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx subl $16, %esp leal -28(%ebp), %edx movl $LC0, %ebx movl $3, %eax movl %edx, %edi movl %ebx, %esi movl %eax, %ecx rep movsl leal -28(%ebp), %eax movl 4(%eax), %eax movl %eax, -16(%ebp) addl $16, %esp popl %ebx popl %esi popl %edi popl %ebp ret .globl _hello3 .def _hello3; .scl 2; .type 32; .endef _hello3: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx subl $16, %esp leal -28(%ebp), %edx movl $LC0, %ebx movl $3, %eax movl %edx, %edi movl %ebx, %esi movl %eax, %ecx rep movsl movl -24(%ebp), %eax movl %eax, -16(%ebp) addl $16, %esp popl %ebx popl %esi popl %edi popl %ebp ret 只要看红色的行,我们可以看到25-27行与74-76行一样,说明hello1与hello3没什么不同, 效率一样。而49-52行比他们多了一行,所以*(a+1)比a[1]和1[a]要低一点。 但是我们看下面的例子。 test1.c与test2.c: 复制代码 代码如下: //1-------------- #include <stdlib.h> void hello() { int *a=(int*)malloc(sizeof(int)*3); int b=*(a+1); free(a); } //2-------------- #include <stdlib.h> void hello() { int *a=(int*)malloc(sizeof(int)*3); int b=a[1]; free(a); } 汇编后完全一样: 复制代码 代码如下: .file "main.c" .text .globl _hello .def _hello; .scl 2; .type 32; .endef _hello: pushl %ebp movl %esp, %ebp subl $40, %esp movl $12, (%esp) call _malloc movl %eax, -12(%ebp) movl -12(%ebp), %eax movl 4(%eax), %eax movl %eax, -16(%ebp) leave ret .def _malloc; .scl 2; .type 32; .endef 所以在堆中使用*(a+n)与a[n]没什么不同,只用在栈中才会有所不同。 学习汇编不是必要,但是它可以让我们知道效率。 |
|
来自: 心不留意外尘 > 《ccpp for hardware》