手机
当前位置:查字典教程网 >编程开发 >C语言 >c文件汇编后函数参数传递的不同之处
c文件汇编后函数参数传递的不同之处
摘要:mac下clang编译后函数的参数先保存在寄存器中(以一定的规则保存),然后在函数中压入栈里,以待后用。例如上篇例子,红色部分:复制代码代码...

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]没什么不同,只用在栈中才会有所不同。

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

【c文件汇编后函数参数传递的不同之处】相关文章:

基于C语言字符串函数的一些使用心得

C++指针作为函数的参数进行传递时需要注意的一些问题

解析sizeof, strlen, 指针以及数组作为函数参数的应用

函数指针的一些概念详解

求子数组最大和的解决方法详解

指向类成员函数的指针其实并非指针

c++中拷贝构造函数的参数类型必须是引用

从汇编看c++中默认构造函数的使用分析

从汇编看c++中多态的应用

构造函数定义为private或者protected的好处

精品推荐
分类导航