C-函数栈帧

news2024/11/30 13:46:46

文章目录

    • 函数栈帧
        • 栈帧创建
        • 栈帧销毁
          • 根据栈帧关系更改值
          • 拓展
    • 可变参数列表
          • 基本原理
          • 整形提升
    • 命令行参数
          • 打印环境变量

函数栈帧

int MyAdd(int a, int b)
{
	int c = 0;
	c = a + b;
	return c;
}
int main()
{
	int x = 0xA;
	int y = 0xB;
	int z =MyAdd(x,y);

	system("pause");
	return 0;
}

image-20230514122652130

--认识寄存器
eax:通用寄存器,保留临时数据,常用于返回值
ebx:通用寄存器,保留临时数据
ebp:栈底寄存器(bottom底部)
esp:栈顶寄存器
eip:指令寄存器,保存当前指令的下一条指令的地址
--汇编指令
mov:数据转移指令
push:数据入栈,同时esp栈顶寄存器也要发生改变
pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub:减法命令
add:加法命令
call:函数调用,1. 压入返回地址 2. 转入目标函数
jump:通过修改eip,转入目标函数,进行调用
ret:恢复返回地址,压入eip,类似pop eip命令
  • call压入返回地址?

根本原因是:函数是可能调用完毕的,就需要返回.所以需要将call命令下一条地址压栈.

  • EIP中被修改为jmp跳转函数的地址到jmp,jmp再跳转到函数地址.然后EIP中再是目标函数地址.

栈帧创建

栈帧销毁

image-20230514135353853

\1. 调用函数之前,需要先形成临时拷贝并且通过寄存器压入栈中,形参形成过程是从右向左的.
\2. 临时空间的开辟,是在对应函数栈帧内部开辟的
\3. 函数调用完毕,栈帧结构被释放掉
\4. 临时变量具有临时性的本质:栈帧具有临时性
\5. 调用函数是有成本的,成本体现在时间和空间上,本质是形成和释放栈帧有成本
\6. 函数调用,因拷贝所形成的临时变量,变量和变量之间的位置关系是有规律的

根据栈帧关系更改值

image-20230514135602519

int MyAdd(int a, int b)
{
	printf("Before:%d\n",b);
	*(&a + 1) = 100;
	printf("After:%d\n", b);

	/*int c = 0;
	c = a + b;*/
	return 0;
}
int main()
{
	int x = 0xA;
	int y = 0xB;
	int z =MyAdd(x,y);

	system("pause");
	return 0;
}
拓展

将main函数ebp地址栈帧相对位置更改实现回原本main函数时去调用其他函数.

只能通过控制停止时间观察现象,具体实现中间插入一个函数的运行还需记录main函数栈帧中原先的地址,由于随机栈等保护措施的存在,现在暂时无法完成.

void bug()
{
	printf("You can see me\n");
	Sleep(10000);
}
int MyAdd(int a, int b)
{
	printf("MyAdd be called!\n");
	*(&a - 1) = (int)bug;
	return 0;
}
int main()
{
	int x = 0xA;
	int y = 0xB;
	int z =MyAdd(x,y);

	system("pause");
	return 0;
}

image-20230514141530685

可变参数列表

函数传参求两个数较大值,形参可以确定的两个.

int FindMax(int x, int y)
{
    if (x > y)
    	return x;
    else
        return y;
} 
int main()
{
    int x = 0;
    int y = 0;
    printf("Please Eneter Two Data# ");
    scanf("%d %d", &x, &y);
    int max = FindMax(x, y);
    printf("max = %d\n", max);
    system("pause");
    return 0;
}

如果函数传参传多个值,需要在多个值中确定最大值,参数个数不确定,编写函数时形参个数无法确定,所以C提供了可变参数列表.

如果没有形式参数,可以给函数传参么?可以的

在C中,只要发生函数调用并且传递参数,必定形成临时拷贝

所谓的临时拷贝本质就是在栈帧中形成的,从右向左依次形成临时拷贝.

  • 可变参数列表至少要有一个参数
基本原理
  1. 通过指针操作以及栈帧中临时变量相对位置获取
int FindMax(int num, ...)
{
	va_list arg;//char* 类型指针
	va_start(arg,num);//让arg指针指向可变参数部分
	int max = va_arg(arg,int);
	for (int i = 0; i < num - 1; i++)
	{
		int cur = va_arg(arg, int);
		if (max < cur)
		{
			max = cur;
		}
	}
	va_end(arg);//指针置空
	return max;
}
int main()
{
	int max = FindMax(5, 0x11, 0x22, 0x33, 0x44, 0x65);
	printf("max=%d\n", max);
	return 0;
}

image-20230515104040388

整形提升
  1. 可变参数中,如果是短整型,一般都需要进行int整形提升.movsx.即使是char类型,在压栈的时候都是4字节.

    通过查看汇编,我们看到,在可变参数场景下:
    \1. 实际传入的参数如果是char,short,float,编译器在编译的时候,会自动进行提升(通过查看汇编,我们都能看到)
    \2. 函数内部使用的时候,根据类型提取数据,更多的是通过int或者double来进行

image-20230515104848125

int FindMax(int num, ...)
{
	va_list arg; //定义可以访问可变参数部分的变量,其实是一个char*类型
	va_start(arg, num); //使arg指向可变参数部分
	int max = va_arg(arg, int); //根据类型,获取可变参数列表中的第一个数据
	for (int i = 0; i < num - 1; i++) {//获取并比较其他的
		int curr = va_arg(arg, int);
		if (max < curr) {
			max = curr;
		}
	} 
	va_end(arg); //arg使用完毕,收尾工作。本质就是讲arg指向NULL
	return max;
}
int main()
{
	char a = '1'; //ascii值: 49
	char b = '2'; //ascii值: 50
	char c = '3'; //ascii值: 51
	char d = '4'; //ascii值: 52
	char e = '5'; //ascii值: 53
	int max = FindMax(5, a, b, c, d, e);
	printf("max = %d\n", max);//max=53
	system("pause");
	return 0;
}
  • 可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途终止,这是可以的,但是,如果你想一开始就访问参数列表中间的参数,那是不行的。
  • 参数列表中至少有一个命名参数。如果连一个命名参数都没有,就无法使用 va_start 。
  • 这些宏是无法直接判断实际存在参数的数量。
  • 这些宏无法判断每个参数的是类型。
  • 如果在 va_arg 中指定了错误的类型,那么其后果是不可预测的。

\1. 可变参数列表对应的函数,最终调用也是函数调用,也要形成栈帧
\2. 栈帧形成前,临时变量是要先入栈的,根据之前所学,参数之间位置关系是固定的
\3. 通过上面汇编的学习,发现了短整型在可变参数部分,会默认进行整形提升,那么函数内部在提取该数据的时候,就要考虑提升之后的值,如果不加考虑,获取数据可能会报错或者结果不正确

_INTSIZEOF(n)的意思:计算一个最小数字x,满足 x>=n && x%4==0,其实就是一种4字节对齐的方式是什么:
比如n是:1,2,3,4 对n进行向 sizeof(int) 的最小整数倍取整的问题 就是 4
比如n是:5,6,7,8 对n进行向 sizeof(int) 的最小整数倍取整的问题 就是 8
所以,简洁版:(n+4-1) & ~(4-1)
原码版:( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

image-20230515123051944

image-20230515123029720

命令行参数

main函数也是一个函数,其实也可以携带参数的
int main( int argc, char *argv[ ], char *envp[ ] )
{
		program-statements
}

那这里是有三个参数的。

第一个参数: argc 是个整型变量,表示命令行参数的个数(含第一个参数)。

第二个参数: argv 是个字符指针的数组,每个元素是一个字符指针,指向一个字符串。这些字符串就是命令行中的每一个参数(字符串)。

第三个参数: envp 是字符指针的数组,数组的每一个原元素是一个指向一个环境变量(字符串)的字符指针.

image-20230515123859289

image-20230515124211158

打印环境变量
int main(int argc, char* argv[], char* env[])
{
	for (int i = 0; env[i]; i++)//env[i]结尾就是NULL
	{
		printf("env[%d]:%s\n", i, env[i] );
	}
}

image-20230515124928101

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/527784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么隐藏回收站?3个方法轻松隐藏回收站!

案例&#xff1a;怎么隐藏回收站 【我不太想把回收站放到桌面上&#xff0c;想把它隐藏了&#xff0c;请问大家有什么好的方法可以隐藏回收站吗&#xff1f;】 回收站是一个非常常见的功能&#xff0c;允许用户恢复已删除的文件。然而&#xff0c;有些人可能不希望回收站一直…

SpringMVC高手进阶

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…

【MySQL】-- 数据库基础

目录 MySQL概述 MySQL初期概念 小结 主流数据库 连接服务器 服务器&#xff0c;数据库&#xff0c;表关系 数据逻辑存储 MySQL架构 SQL分类 存储引擎 存储引擎 查看存储引擎 MySQL概述 #问&#xff1a;什么是数据库&#xff1f; MySQL初期概念 这个所谓的mysql严格…

从零开始Vue3+Element Plus后台管理系统(七)——手写一个简单的多页签组件

以前都是用别人现成的多页签组件&#xff0c;自己也想尝试下做个Vue3的版本&#xff0c;目前还只有基本功能&#xff0c;慢慢完善。 主要思路 使用 Pinia 记录页签数据、处理操作初始状态没有页签数据&#xff0c;使用默认路由数据填充右击页签&#xff0c;显示更多关闭操作…

移动云与启明星辰联合发布移动云|星辰安全品牌

数字中国时代&#xff0c;企业数字化转型不断深化&#xff0c;云安全市场发展持续高增&#xff0c;其安全更需自主可控、全程可信。基于此&#xff0c;移动云和启明星辰共同打造移动云|星辰安全品牌&#xff0c;聚力协行共筑安全云的压舱石&#xff0c;携手共塑中国云安全产业发…

原神服务器服务端多人联机教程

原神服务器服务端多人联机教程 大家好&#xff0c;我是艾西在上一篇文章中我们说了win系统服务器怎么搭建原神服务端&#xff0c;在最后结尾时有带一嘴怎么改为多人联机但不是很详细。哪么这篇文章艾西会给小伙伴们说清楚原神服务端怎么改为多人联机&#xff0c;毕竟玩游戏肯定…

MySQL高级语句(一)

一、SQL高级语句 1、 SELECT 显示表格中一个或数个栏位的所有资料 语法&#xff1a;SELECT "字段" FROM "表名"; select * from test1; select name from test1; select name,sex from test1;2、DISTINCT 不显示重复的内容 语法&#xff1a;SELECT D…

pdf怎么转换成ppt?4种方法1分钟处理

​ pdf怎么转换成ppt&#xff1f;在日常的办公中&#xff0c;经常需要进行PDF文件格式的转换。例如&#xff0c;我们从互联网上下载的许多资料都是以PDF格式保存的。此外&#xff0c;在使用Microsoft Office时&#xff0c;有些用户需要将Word文档转换为PDF格式&#xff0…

MySQL的概念、编译安装,以及自动补全

一.数据库的基本概念 1、数据&#xff08;Data&#xff09; • 描述事物的符号记录 • 包括数字&#xff0c;文字&#xff0c;图形&#xff0c;图像&#xff0c;声音&#xff0c;档案记录等 • 以“记录”形式按统一的格式进行存储 2、表 • 将不同的记录组织在一起 • …

JavaWeb08(MVC应用02[家居商城]连接数据库)

目录 一.绑定分类 1.1 效果预览 1.2 代码实现 ①底层代码 ②前端代码 二.绑定所有商品 2.1 效果预览 2.2.代码实现 ①底层代码 ②前端代码 三.分类查询 3.1效果预览 3.2代码实现 ①底层代码 ②前端代码 四.模糊查询 4.1 效果预览 4.2代码实现 ①底层代码 ②前…

一图看懂 zipp 模块:ZipFile 的一些兼容子类和补充接口,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 zipp 模块&#xff1a;ZipFile 的一些兼容子类和补充接口&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块图&#x1f9ca;类关…

直观理解torch.gather函数(带图)

直观理解torch.gather函数 1. gather的作用 因为深度学习里面&#xff0c;像分类或者分割&#xff0c;有时候去进行loss计算或准确度计算的时候&#xff0c;需要挑选某个维度特定的值&#xff0c;所以有了这么个函数。注意不要高估这个函数的能力&#xff0c;这个函数只是在指…

大数据技术之Sqoop

第1章 Sqoop简介 Sqoop是一款开源的工具&#xff0c;主要用于在Hadoop(Hive)与传统的数据库(mysql、postgresql…)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如 &#xff1a; MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop的HDFS中&…

破案小说中的《人月神话》和女装

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 在破案小说《谁是凶手》中&#xff0c;《人月神话》、《程序员修炼之道》以及女装作为素材出现了。 成功学&#xff08;鸡汤学&#xff09;书籍《用所有的存在与世界相会》…

如何制定一套有效的期货交易系统策略?

期货交易是一项全球性的金融交易&#xff0c;对于投资者来说&#xff0c;制定有效的期货交易系统策略是至关重要的。在制定期货交易策略时&#xff0c;需要考虑市场趋势、资产种类、交易成本、仓位控制等多个方面。 很多刚进入期货市场的朋友&#xff0c;甚至很多做了很久期货…

JS代码优化——逻辑判断

文章目录 JavaScript 语法篇嵌套层级优化多条件分支的优化处理使用数组新特性简化逻辑判断**多条件判断****判断数组中是否所有项都满足某条件****判断数组中是否有某一项满足条件** **函数默认值**使用默认参数使用解构与默认参数复杂数据解构 策略模式优化分支逻辑处理 JavaS…

Mars3d实现加载gif动图

官网有相关示例参考&#xff1a;功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技 功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技 方式1&#xff1a; // [终点]绘制台风当前位置gif点 const gifGraphic new mars3d.graphic.DivGraphic({ position: [endItem.lon, e…

【人力资源管理】第3集 免费开源ERP: Odoo 16 hr_holidays管理员工休假和缺勤 构建一体化企业人力资源管理

文章目录 前言一、管理员工休假二、批准或者拒绝休假申请三 、简单报表工具四 、使用功能1.管理休假申请2.报告 总结 前言 管理员工休假和缺勤。 一、管理员工休假 跟踪所有员工的假期 跟踪每位员工的休假天数。员工输入请求&#xff0c;经理对请求进行审批和验证&#xff0…

MYSQL-数据库管理.3(用户管理及用户权限)

一、关系型数据库 数据结构 二维表格 库 -> 表 -> 列&#xff08;字段&#xff09;&#xff1a;用来描述对象的一个属性 行&#xff08;记录&#xff09;&#xff1a;用来描述一个对象的信息 二、非关系型数…

能成事的表达笔记

为什么需要好的沟通&#xff1f; 一.让自己舒服 二.让别人乐意 愿意听听得懂听完愿意配合你 共赢 沟通是思维和视角的改变 向上沟通 &#xff08;领导&#xff0c;客户&#xff09; 是最高效的职场成长路径 痛点&#xff1a; 出于恐惧而挖掘不到真实的需求 一味听从权威…