c、数组与汇编

  上次的“c调用汇编”使用的clang编译器,而且使用的是mac 64位系统。当时感觉写的汇编怪怪的,

今天闲来无事,就在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.s:

    .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例子:

 1 void hello1()
 2 {
 3     int a[3]={1,2,3};
 4         int b=a[1];
 5 }
 6 void hello2()
 7 {
 8     int a[3]={1,2,3};
 9     int b=*(a+1);
10 } 
11 void hello3()
12 {
13     int a[3]={1,2,3};
14     int b=1[a]; //这也对?
15 }           

如果看的够仔细的话,三个函数没什么不同就是对数组a[1]的不同(当然函数名除外).

gcc -S test.c 后:

 

 1     .file    "test.c"
 2     .data
 3     .align 4
 4 LC0:
 5     .long    1
 6     .long    2
 7     .long    3
 8     .text
 9     .globl    _hello1
10     .def    _hello1;    .scl    2;    .type    32;    .endef
11 _hello1:
12     pushl    %ebp
13     movl    %esp, %ebp
14     pushl    %edi
15     pushl    %esi
16     pushl    %ebx
17     subl    $16, %esp
18     leal    -28(%ebp), %edx
19     movl    $LC0, %ebx
20     movl    $3, %eax
21     movl    %edx, %edi
22     movl    %ebx, %esi
23     movl    %eax, %ecx
24     rep movsl
25     movl    -24(%ebp), %eax
26     movl    %eax, -16(%ebp)
27     addl    $16, %esp
28     popl    %ebx
29     popl    %esi
30     popl    %edi
31     popl    %ebp
32     ret
33     .globl    _hello2
34     .def    _hello2;    .scl    2;    .type    32;    .endef
35 _hello2:
36     pushl    %ebp
37     movl    %esp, %ebp
38     pushl    %edi
39     pushl    %esi
40     pushl    %ebx
41     subl    $16, %esp
42     leal    -28(%ebp), %edx
43     movl    $LC0, %ebx
44     movl    $3, %eax
45     movl    %edx, %edi
46     movl    %ebx, %esi
47     movl    %eax, %ecx
48     rep movsl
49     leal    -28(%ebp), %eax
50     movl    4(%eax), %eax
51     movl    %eax, -16(%ebp)
52     addl    $16, %esp
53     popl    %ebx
54     popl    %esi
55     popl    %edi
56     popl    %ebp
57     ret
58     .globl    _hello3
59     .def    _hello3;    .scl    2;    .type    32;    .endef
60 _hello3:
61     pushl    %ebp
62     movl    %esp, %ebp
63     pushl    %edi
64     pushl    %esi
65     pushl    %ebx
66     subl    $16, %esp
67     leal    -28(%ebp), %edx
68     movl    $LC0, %ebx
69     movl    $3, %eax
70     movl    %edx, %edi
71     movl    %ebx, %esi
72     movl    %eax, %ecx
73     rep movsl
74     movl    -24(%ebp), %eax
75     movl    %eax, -16(%ebp)
76     addl    $16, %esp
77     popl    %ebx
78     popl    %esi
79     popl    %edi
80     popl    %ebp
81     ret

只要看红色的行,我们可以看到25-27行与74-76行一样,说明hello1与hello3没什么不同,

效率一样。而49-52行比他们多了一行,所以*(a+1)比a[1]和1[a]要低一点。

 但是我们看下面的例子。

test1.c与test2.c:

View Code
 //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);
}

 

汇编后完全一样:

View Code
 1     .file    "main.c"
 2     .text
 3     .globl    _hello
 4     .def    _hello;    .scl    2;    .type    32;    .endef
 5 _hello:
 6     pushl    %ebp
 7     movl    %esp, %ebp
 8     subl    $40, %esp
 9     movl    $12, (%esp)
10     call    _malloc
11     movl    %eax, -12(%ebp)
12     movl    -12(%ebp), %eax
13     movl    4(%eax), %eax
14     movl    %eax, -16(%ebp)
15     leave
16     ret
17     .def    _malloc;    .scl    2;    .type    32;    .endef

  所以在堆中使用*(a+n)与a[n]没什么不同,只用在栈中才会有所不同。

  学习汇编不是必要,但是它可以让我们知道效率。

 

posted @ 2013-04-19 23:17  除e尘  阅读(341)  评论(0编辑  收藏  举报