首页 技术 正文
技术 2022年11月15日
0 收藏 404 点赞 4,280 浏览 1136 个字

按照C编译器的约定调用函数时压栈的顺序是从右向左,并且返回值是保存在eax寄存器当中。这个命题本该是成立的,下面用一个小程序来反汇编观察执行过程:

#include<stdio.h>int add(int x, int y){
return x+y;
}int main(){
int eax=0;
int z =0;
int x =6;
int y =5;z=add(x,y);__asm__(
"movl %%eax, %0"
:"+b"(eax)
:"m"(x)
);printf("z is %d\n", z);
printf("eax is %d\n", eax);
return 0;
}

代码解释一下,asm的代码中movl %%eax, %0的意思是把寄存器eax的值赋值给咱们程序的eax变量当中。但为什么执行结果却是:

z is 11
eax is 0

理论上应该是x和y相加返回的结果才对啊。反汇编一下此exe程序:

关于C语言函数调用压栈和返回值问题的疑惑

关于C语言函数调用压栈和返回值问题的疑惑

上面是main函数,看下图

关于C语言函数调用压栈和返回值问题的疑惑

esp自减了20h,说明开辟了20h也就是32字节的栈空间,再看下图:

关于C语言函数调用压栈和返回值问题的疑惑

[esp+1ch]对应的是程序中的变量eax,也就是把eax压在了esp+28处,此变量是int型4个字节,所以刚好对应的是栈底元素;[esp+18h]对应的是z也就是esp+24处,[esp+10h]对应的是x也就是esp+16处,[esp+14h]对应的是y。再看下图

关于C语言函数调用压栈和返回值问题的疑惑

先把[esp+10h]的值也就是x的值赋给eax,再把[esp+14h]的值也就是y的值赋给edx,再分别把它们赋给[esp+4]和[esp]处,注意这里没用push指令压栈,但原理却是一样,因为用的是栈指针esp,还需要注意的是因为不是使用push指令,所以不是说谁先执行谁就先压栈,而是观察esp指向的位置来确定压栈的先后顺序,因为[esp]指向的是栈顶元素。所以这里就解释了先把y压栈,再把x压栈,确实是从右向左压栈

接下来再看add调用:

关于C语言函数调用压栈和返回值问题的疑惑

注意上面call add指令会先把eip压栈,相当于esp=esp-4,并且这里还执行了push ebp指令,所以esp又自减了4,那么x的值就不再是入栈时候的[esp]了,而是[esp+8],所以y的值也不再是[esp+4]而是[esp+12],所以这里出栈的时候也不是看执行的先后顺序,而是x本身就处于栈顶,相加后结果保存在eax里。然后再回到main函数

关于C语言函数调用压栈和返回值问题的疑惑

调用完add后把eax的值赋值给了z,这就说明函数的返回值确实是保存在eax中。但为什么打印出来的eax却是0呢。

接着往下看,

关于C语言函数调用压栈和返回值问题的疑惑

首先把程序中eax变量的值赋给了eax寄存器,那当然就是0了。所以现在深入理解了C语言嵌入汇编的执行过程,就算指定了”+b”赋给ebx寄存器,但编译器还是会先把变量的值赋给eax寄存器,再赋值给ebx,返回也是一样的原理,如下图:

关于C语言函数调用压栈和返回值问题的疑惑

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,075
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,551
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,399
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,176
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,811
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,893