c文件汇编后函数参数传递的不同之处
来源:本站原创|时间:2020-01-10|栏目:C语言|点击: 次
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语言
下一篇:STL 的string类怎么啦
本文标题:c文件汇编后函数参数传递的不同之处
本文地址:https://www.xiuzhanwang.com/a1/Cyuyan/3922.html
您可能感兴趣的文章
- 01-10fatal error LNK1104: 无法打开文件“libc.lib”的解决方法
- 01-10显示任何进程加载的DLL文件的代码
- 01-10深入探讨linux下进程的最大线程数、进程最大数、进程打开的文
- 01-10使用Inotify 监控目录与文件的方法详解
- 01-10用c 获取文件MD5值的实现方法
- 01-10用C实现添加和读取配置文件函数
- 01-10在vs2010中,输出当前文件路径与源文件当前行号的解决方法
- 01-10C++中简单读写文本文件的实现方法
- 01-10C语言文件操作函数大全(超详细)
- 01-10深入探讨:linux中遍历文件夹下的所有文件
阅读排行
本栏相关
- 04-02c语言函数调用后清空内存 c语言调用
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言的正则匹配函数 c语言正则表达
- 04-02c语言用函数写分段 用c语言表示分段
- 04-02c语言中对数函数的表达式 c语言中对
- 04-02c语言编写函数冒泡排序 c语言冒泡排
- 04-02c语言没有round函数 round c语言
- 04-02c语言分段函数怎么求 用c语言求分段
- 04-02C语言中怎么打出三角函数 c语言中怎
- 04-02c语言调用函数求fibo C语言调用函数求
随机阅读
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 01-10C#中split用法实例总结
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-10delphi制作wav文件的方法
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 04-02jquery与jsp,用jquery
- 01-11ajax实现页面的局部加载
- 01-10SublimeText编译C开发环境设置
- 08-05织梦dedecms什么时候用栏目交叉功能?