汇编和c语言函数的参数传递,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
void hello()
{
int *a=(int*)malloc(sizeof(int)*3);
int b=*(a+1);
free(a);
}
//2--------------
#include
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文件汇编后函数参数传递的不同之处相关推荐
- php文件读写用什么函数,php中常用文件操作读写函数介绍_PHP教程
本文章介绍了下面几个常用的文件操作函数 file_get_contents 读取整个文件内容 fopen 创建和打开文件 fclose 关闭文件 fgets 读取文件一行内容 file_exists ...
- 【ATT 与 Intel】汇编与C语言相互调用及内联汇编
目录 一.ATT 与 Intel 二.函数调用的约定 三.C语言调用汇编程序 四.汇编程序调用C语言 五.内联汇编 5.1.基本asm格式 5.2.扩展asm格式 5.3.使用占位符来替代寄存器名称 ...
- python调用js库中的函数_Python 调用JS文件中的函数
Python 调用JS文件中的函数 1.安装PyExecJS第三方库 2.导入库:import execjs 3.调用JS文件中的方法 Passwd = execjs.compile(open(r&q ...
- php打开文件读写函数,php中常用文件操作读写函数介绍
本文章介绍了下面几个常用的文件操作函数 file_get_contents 读取整个文件内容 fopen 创建和打开文件 fclose 关闭文件 fgets 读取文件一行内容 file_exists ...
- c语言中结构体头文件是什么,函数形参里有结构体指针,为什么在头文件生
满意答案 lam950 2017.04.08 采纳率:59% 等级:8 已帮助:913人 C语言用结构体指针作函数参数 这种方式比用结构体变量作函数参数效率高,因为无需传递各个成员的值,只需传递 ...
- 汇编c语言基础教程编程达人,编程达人 《汇编、C语言基础教程》第二章 汇编基础2.2 寄存器...
2.2 寄存器 本节只需要了解 处理器(CPU)由运算器.控制器.寄存器.输入设备和输出设备组成,这些器件由处理数据总线相连.[此节内容是为了了解寄存器相关知识,不需要掌握] 它们在处理器中,分工明确 ...
- VS2010中如果忘记函数所在的头文件或者忘记函数的输入输出参数类型怎么办?...
先随便找一个熟悉的函数,右击-转到定义,然后写出目标函数,右击-转到定义 转载于:https://www.cnblogs.com/bewolf/p/4386391.html
- linux中creat-file函数,Linux应用程序-文件编程-file_creat()函数的问题
* **系统调用:创建一个文件 **函数原型:int creat(const char *filename,mode_t mode); **参数:filename->要创建的文件名(包含路径,缺 ...
- 怎么使用远程php文件的函数调用函数,一个读取远程文件的PHP函数
一个读取远程文件的函数,非常好用 function urlfopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE , ...
最新文章
- ASP.NET Core EFCore 之Code First
- android获取app用户数据,Android 原生app获取用户授权访问Autodesk云应用数据
- Linux驱动修炼之道-SPI驱动框架源码分析(中)
- 设计一个简单的缓存容器
- 猜字游游戏,while执行10次(Python)
- const的用法(C语言)
- 看美国如何实现农业大数据的建设
- 函数指针数组指针+结构体数组
- 【Java】Java8新特性Lambda表达式和Stream API
- 使用nohup让程序在远程主机后台运行
- Linux---Samba文件共享服务
- 公文排版字体要求以及印制要求
- python基础入门(超详细)
- Ito‘s lemma伊藤引理
- 每一代内存的读写速度大概是多少?
- 漫威宇宙影视作品及观看顺序
- AutoIt上路03-添加工具栏
- 终于懂得孤独是躲不开的单行道
- CodeForces 1015 C Songs Compression
- repo init报错error.GitError: manifests rev-list (u'^2736dfd46e8a30cf59a9cd6e93d9e56e87021f2a', 'HEAD',
热门文章
- [Python+MATLAB] 在Python中使用MATLAB (持续更新中)
- [高光谱] Hyperspectral-Classification Pytorch 的高光谱场景的通用类 HyperX
- 【Proteus仿真8086】定时器8253产生波形发生器
- AD16从两层切到显示一层的视图shift+s
- 五分钟快速过完Verilog HDL基本概念(3)语法讲解
- nginx的web基础
- Boosting and AdaBoost
- javascript 布尔类型
- 终于能理解kmp算法了
- [转载] python 中的时间,日期,时间戳互相转换