c文件匯編后函數(shù)參數(shù)傳遞的不同之處
更新時間:2013年11月15日 15:15:02 作者:
在w7 32位系統(tǒng)下把c文件匯編后,確實與mac后的差異很大。可不僅僅是寄存器eax與rax的區(qū)別。我想說的是函數(shù)參數(shù)傳遞的不同
mac下clang編譯后函數(shù)的參數(shù)先保存在寄存器中(以一定的規(guī)則保存),然后在函數(shù)中壓入棧里,
以待后用。例如上篇例子,紅色部分:
復(fù)制代碼 代碼如下:
.global _decToBin
_decToBin:
pushq %rbp
movq %rsp,%rbp
movq %rdi,-8(%rbp) #第一個參數(shù),保存在rdi中
movq %rsi,-16(%rbp) #第二個參數(shù),保存在rsi中
movq -8(%rbp),%rax
movq -16(%rbp),%rbx
movq $63,%rcx
......
popq %rbp
ret
而我在w7下使用cygwin安裝的gcc編譯test.c文件:
test.c:
復(fù)制代碼 代碼如下:
int hello(int a,int b,int c,int d)
{
return b;
}
test.c
復(fù)制代碼 代碼如下:
.file "test.c"
.text
.globl _hello
.def _hello; .scl 2; .type 32; .endef
_hello:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax #說明參數(shù)是函數(shù)在使用其值之前就已經(jīng)壓入棧中
popl %ebp
ret
這說明clang與gcc使用了兩種不同的規(guī)則(網(wǎng)上有很多介紹函數(shù)值傳遞的不同規(guī)則的,我就不介紹了)。
所以不同的平臺不同的編譯器要不同的對待。以上算是上次的不足補充吧。
下面來看看數(shù)組:
test.c例子:
復(fù)制代碼 代碼如下:
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]; //這也對?
}
如果看的夠仔細的話,三個函數(shù)沒什么不同就是對數(shù)組a[1]的不同(當然函數(shù)名除外).
gcc -S test.c 后:
復(fù)制代碼 代碼如下:
.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:
復(fù)制代碼 代碼如下:
//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);
}
匯編后完全一樣:
復(fù)制代碼 代碼如下:
.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]沒什么不同,只用在棧中才會有所不同。
學(xué)習(xí)匯編不是必要,但是它可以讓我們知道效率。
相關(guān)文章
C++實現(xiàn)inline hook的原理及應(yīng)用實例
這篇文章主要介紹了C++實現(xiàn)inline hook的原理及應(yīng)用,需要的朋友可以參考下2014-08-08C語言中settimeofday函數(shù)和gettimeofday函數(shù)的使用
這篇文章主要介紹了C語言中的settimeofday函數(shù)和gettimeofday函數(shù)的使用,注意settimeofday()函數(shù)只返回0和-1,需要的朋友可以參考下2015-08-08C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)詳解
這篇文章主要為大家介紹了C++的靜態(tài)成員變量和靜態(tài)成員函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-12-12淺談返回函數(shù)內(nèi)部new分配的內(nèi)存的引用
下面小編就為大家?guī)硪黄獪\談返回函數(shù)內(nèi)部new分配的內(nèi)存的引用。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12C++?this原理與可變參數(shù)及友元函數(shù)友元類分步詳解用法
可變參數(shù)模板(variadic?templates)是C++11新增的強大的特性之一,它對模板參數(shù)進行了高度泛化,能表示0到任意個數(shù)、任意類型的參數(shù),這篇文章主要介紹了C++?this原理與可變參數(shù)及友元函數(shù)友元類2022-11-11