C语言函数调用参数压栈的相关问题Word文档下载推荐.docx
《C语言函数调用参数压栈的相关问题Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《C语言函数调用参数压栈的相关问题Word文档下载推荐.docx(13页珍藏版)》请在冰豆网上搜索。
![C语言函数调用参数压栈的相关问题Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-1/22/1ff488cd-d0bc-41df-a575-36fa288b446a/1ff488cd-d0bc-41df-a575-36fa288b446a1.gif)
∙1
∙2
∙3
∙4
∙5
∙6
∙7
∙8
∙9
∙10
∙11
∙12
∙13
∙14
在64位Ubuntu的系统下的运行结果是:
addressofa1ec62c.
addressofb1ec628.
32位Ubuntu的结果是:
addressofabfd03290.
addressofbbfd03294.
可以看出,首先,不同的体系结构,栈增长的方向也不同,有的是从低地址向高地址方向增长,有的是从高地址向低地址方向增长。
可以用以下的代码来判断栈的增长方向:
typedefenum{
LOW_TO_HIGH,
HIGH_TO_LOW,
LEFT_TO_RIGHT,
RIGHT_TO_LEFT,
}stack_direc_t;
intstack_grow_direc()
staticchar*p=NULL;
charc;
if(p==NULL){
p=&
c;
stack_grow_direc();
}
else{
Firstinstackaddressis%x.\n"
p);
Secondinstackaddressis%x.\n"
c);
if(&
c>
p){
Stackgrowsfromlowaddresstohighaddress!
\n"
);
returnLOW_TO_HIGH;
Stackgrowsfromhighaddresstolowaddress!
returnHIGH_TO_LOW;
∙15
∙16
∙17
∙18
∙19
∙20
∙21
∙22
∙23
∙24
∙25
∙26
∙27
∙28
∙29
函数调用时栈里都有什么
以参数从左到右入栈为例:
pusharg0--HighAddress
pusharg1
...
pushargn
pusheip
pushebp--Lowaddress
32位系统和64位系统函数调用时,参数入栈方式有不同么?
这个问题在不久之前被人问题,当时傻了,我一直以来只关注过32位系统的参数入栈方式,一直以为64位系统也是一样,没有什么不同,现在归纳起来有两点:
∙64位系统先把传入参数放在寄存器里面,在被调函数的具体实现中把寄存器的值入栈,然后再去栈中取参数
∙64位系统栈中参数存放的顺序是从左至右的(因为先经历了寄存器传值)
看下面的反汇编:
C代码同上面一样
Ubuntu32位反汇编:
804846d:
55push%ebp
804846e:
89e5mov%esp,%ebp
8048470:
83e4f0and$0xfffffff0,%esp
8048473:
83ec10sub$0x10,%esp
8048476:
c7442404020000movl$0x2,0x4(%esp)
804847d:
00
804847e:
c7042401000000movl$0x1,(%esp)
8048485:
e88affffffcall8048414<
test>
804848a:
b800000000mov$0x0,%eax
8048414:
8048415:
8048417:
83ec18sub$0x18,%esp
804841a:
b860850408mov$0x8048560,%eax
804841f:
8d5508lea0x8(%ebp),%edx
8048422:
89542404mov%edx,0x4(%esp)
8048426:
890424mov%eax,(%esp)
8048429:
e812ffffffcall8048340<
printf@plt>
8048466:
Ubuntu64位反汇编:
40056e:
55push%rbp
40056f:
4889e5mov%rsp,%rbp
400572:
be02000000mov$0x2,%esi
400577:
bf01000000mov$0x1,%edi
40057c:
e8acffffffcallq40052d<
400581:
40052d:
40052e:
400531:
4883ec10sub$0x10,%rsp
400535:
897dfcmov%edi,-0x4(%rbp)
400538:
8975f8mov%esi,-0x8(%rbp)
40053b:
488d45fclea-0x4(%rbp),%rax
40053f:
4889c6mov%rax,%rsi
400542:
bf14064000mov$0x400614,%edi
400547:
40054c:
e8bffeffffcallq400410<
400567:
∙30
∙31
∙32
∙33
∙34
∙35
∙36
∙37
∙38
∙39
∙40
∙41
∙42
∙43
∙44
∙45
∙46
∙47
∙48
∙49
∙50
∙51
∙52
∙53
∙54
∙55
∙56
∙57
∙58
∙59
∙60
看32位的ubuntu操作系统,8048476:
的确是把参数直接入栈,2先入栈,1后入栈。
再来看64位的ubuntu操作系统,2和1根本就没有放入到栈中,而是放到了寄存器esi和edi中。
再来看64位系统test的实现,先把edi入栈,再把esi入栈,这就是为什么函数看起来像是从左到右入栈的原因了。