c:变参函数:汇编解析;va_list;marco 宏:__VA_ARGS__
文章目录
- 参考
- gcc 内部的宏定义
- 代码
- 汇编
- 调用
- 在 SEI CERT C++ Coding Standard 这个标准里
- 示例
- 实例
- 宏里的使用
参考
https://git.sr.ht/~gregkh/presentation-security/blob/3547183843399d693c35b502cf4a313e256d0dd8/security-stuff.pdf
gcc 内部的宏定义
宏定义:
使用的时builtin_va_end 宏定义。
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
使用到了下列内置函数来实现va-start、end、arg相关的宏。
/* Expand EXP, a call to __builtin_va_start. */static rtx
expand_builtin_va_start (tree exp)
{rtx nextarg;tree valist;location_t loc = EXPR_LOCATION (exp);
代码
int add(int first, int second, ... )
{int r=first + second;va_list va;;;va_start(va, second);while(int v= va_arg(va,int)){r+=v;}va_end(va);return r;
}
汇编
962 0000000000400c56 <add(int, int, ...)>:963 400c56: 55 push %rbp964 400c57: 48 89 e5 mov %rsp,%rbp965 400c5a: 48 83 ec 68 sub $0x68,%rsp 申请的栈空间是 0x68,但是使用的远远大于这个值。966 400c5e: 89 bd 2c ff ff ff mov %edi,-0xd4(%rbp) 六个寄存器参数都用上了967 400c64: 89 b5 28 ff ff ff mov %esi,-0xd8(%rbp) 而且将这六个参数放到超远的栈上。968 400c6a: 48 89 95 60 ff ff ff mov %rdx,-0xa0(%rbp)969 400c71: 48 89 8d 68 ff ff ff mov %rcx,-0x98(%rbp)970 400c78: 4c 89 85 70 ff ff ff mov %r8,-0x90(%rbp)971 400c7f: 4c 89 8d 78 ff ff ff mov %r9,-0x88(%rbp)972 400c86: 84 c0 test %al,%al 看着调用一直时0,是否用到floating 的变量?几个973 400c88: 74 20 je 400caa <add(int, int, ...)+0x54> 如果又floating的数值,将floating寄存器的值放到 栈974 400c8a: 0f 29 45 80 movaps %xmm0,-0x80(%rbp) floating的值放到floating 寄存器。975 400c8e: 0f 29 4d 90 movaps %xmm1,-0x70(%rbp)976 400c92: 0f 29 55 a0 movaps %xmm2,-0x60(%rbp)977 400c96: 0f 29 5d b0 movaps %xmm3,-0x50(%rbp)978 400c9a: 0f 29 65 c0 movaps %xmm4,-0x40(%rbp)979 400c9e: 0f 29 6d d0 movaps %xmm5,-0x30(%rbp)980 400ca2: 0f 29 75 e0 movaps %xmm6,-0x20(%rbp)981 400ca6: 0f 29 7d f0 movaps %xmm7,-0x10(%rbp)982 400caa: 8b 95 2c ff ff ff mov -0xd4(%rbp),%edx983 400cb0: 8b 85 28 ff ff ff mov -0xd8(%rbp),%eax984 400cb6: 01 d0 add %edx,%eax 第一个和第二个参数相加放到eax985 400cb8: 89 85 4c ff ff ff mov %eax,-0xb4(%rbp) 然后放到 栈986 400cbe: c7 85 30 ff ff ff 10 movl $0x10,-0xd0(%rbp) 将16 放到 栈987 400cc5: 00 00 00988 400cc8: c7 85 34 ff ff ff 30 movl $0x30,-0xcc(%rbp) 将0x30 放到栈989 400ccf: 00 00 00990 400cd2: 48 8d 45 10 lea 0x10(%rbp),%rax 将rbp + 16 的值放到rax,使用到了上一个函数栈。991 400cd6: 48 89 85 38 ff ff ff mov %rax,-0xc8(%rbp) ,放到栈992 400cdd: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax 将rbp -0xb0的地址放到rax993 400ce4: 48 89 85 40 ff ff ff mov %rax,-0xc0(%rbp) 放到栈994 400ceb: 8b 85 30 ff ff ff mov -0xd0(%rbp),%eax 将rbp-0xd0的值放到eax995 400cf1: 83 f8 2f cmp $0x2f,%eax 对比0x2f 为什么比对2f?996 400cf4: 77 23 ja 400d19 <add(int, int, ...)+0xc3>997 400cf6: 48 8b 85 40 ff ff ff mov -0xc0(%rbp),%rax998 400cfd: 8b 95 30 ff ff ff mov -0xd0(%rbp),%edx999 400d03: 89 d2 mov %edx,%edx1000 400d05: 48 01 d0 add %rdx,%rax1001 400d08: 8b 95 30 ff ff ff mov -0xd0(%rbp),%edx1002 400d0e: 83 c2 08 add $0x8,%edx1003 400d11: 89 95 30 ff ff ff mov %edx,-0xd0(%rbp)1004 400d17: eb 12 jmp 400d2b <add(int, int, ...)+0xd5>1005 400d19: 48 8b 85 38 ff ff ff mov -0xc8(%rbp),%rax1006 400d20: 48 8d 50 08 lea 0x8(%rax),%rdx1007 400d24: 48 89 95 38 ff ff ff mov %rdx,-0xc8(%rbp)1008 400d2b: 8b 00 mov (%rax),%eax1009 400d2d: 89 85 48 ff ff ff mov %eax,-0xb8(%rbp)1010 400d33: 83 bd 48 ff ff ff 00 cmpl $0x0,-0xb8(%rbp)1011 400d3a: 74 0e je 400d4a <add(int, int, ...)+0xf4>1012 400d3c: 8b 85 48 ff ff ff mov -0xb8(%rbp),%eax1013 400d42: 01 85 4c ff ff ff add %eax,-0xb4(%rbp) 将 eax 加到栈里1014 400d48: eb a1 jmp 400ceb <add(int, int, ...)+0x95>1015 400d4a: 8b 85 4c ff ff ff mov -0xb4(%rbp),%eax 最终的结果放到eax1016 400d50: c9 leaveq1017 400d51: c3 retq
调用
int main()
{
printf( "abc=%d\n", add(1,3,4,5,8,9,10);
return 1;
}
0000000000400968 <main>:400968: 55 push %rbp400969: 48 89 e5 mov %rsp,%rbp40096c: 48 83 ec 08 sub $0x8,%rsp 按16 字节对齐。多8个字节占栈,如果多出来一个参数400970: 6a 0a pushq $0xa400972: 41 b9 09 00 00 00 mov $0x9,%r9d400978: 41 b8 08 00 00 00 mov $0x8,%r8d40097e: b9 05 00 00 00 mov $0x5,%ecx400983: ba 04 00 00 00 mov $0x4,%edx400988: be 03 00 00 00 mov $0x3,%esi40098d: bf 01 00 00 00 mov $0x1,%edi400992: b8 00 00 00 00 mov $0x0,%eax 把 eax 清空400997: e8 aa fe ff ff callq 400846 <add(int, int, ...)>40099c: 48 83 c4 10 add $0x10,%rsp 释放栈4009a0: 89 c6 mov %eax,%esi4009a2: bf b2 0a 40 00 mov $0x400ab2,%edi4009a7: b8 00 00 00 00 mov $0x0,%eax4009ac: e8 3f fd ff ff callq 4006f0 <printf@plt>4009b1: b8 01 00 00 00 mov $0x1,%eax4009b6: c9 leaveq4009b7: c3 retq
在 SEI CERT C++ Coding Standard 这个标准里
提到了更安全的C++定义方式。 这种方式将编程从运行时变参,转移到了编译时,更安全。
示例
https://en.cppreference.com/w/cpp/language/parameter_pack
#include <iostream>void tprintf(const char* format) // base function
{std::cout << format;
}
、、 这个会产生多少个函数来?
template<typename T, typename... Targs>
void tprintf(const char* format, T value, Targs... Fargs) // recursive variadic function
{for ( ; *format != '\0'; format++ ) {if ( *format == '%' ) {std::cout << value;tprintf(format+1, Fargs...); // recursive callreturn;}std::cout << *format;}
}int main()
{tprintf("% world% %\n","Hello",'!',123);
}
实例
变参传递到另一个函数里:
static inline void abc(int level, const char *format, ...)
{char buff[UMAX_LOG_SIZE];int msgLen;va_list arglist;memset(buff, 0, sizeof(buff));va_start(arglist, format);msgLen = vsnprintf(buff, UMAX_LOG_SIZE, format, arglist);va_end(arglist);
宏里的使用
下面这个宏,只包含有,三个点所代表的参数;不包含三个点以外有名称的参数。
__VA_ARGS__
#define _FUNC1_(tn, constness, ct, Method, ...) \
class mock_##Method { \
public:\RESULT_(tn, __VA_ARGS__) ct Method( \ // 这里__VA_ARGS__, 不包含 tn,constness,ct和Method
相关文章:
c:变参函数:汇编解析;va_list;marco 宏:__VA_ARGS__
文章目录 参考gcc 内部的宏定义代码汇编调用在 SEI CERT C Coding Standard 这个标准里示例实例宏里的使用 参考 https://git.sr.ht/~gregkh/presentation-security/blob/3547183843399d693c35b502cf4a313e256d0dd8/security-stuff.pdf gcc 内部的宏定义 宏定义:…...
eclipse安装教程(2021版)
第一步:下载JDK (下载地址) Java SE - Downloads 第二步 根据自己电脑的系统,选择相应的版本x64代表64位,x86代表32位。点击相应的JDK进行下载 点击之后会出现一个对话框 同意之后下载。(记住下载到哪,打…...
计算机网络重点概念整理-第二章 物理层【期末复习|考研复习】
第二章 物理层 【期末复习|考研复习】 计算机网络系列文章传送门: 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 第二章 物理层 【期末复习|考研复习…...
【计算机网络】从输入URL到页面都显示经历了什么??
文字总结 ① DNS 解析:当用户输入一个网址并按下回车键的时候,浏览器获得一个域名,而在实际通信过程中,我们需要的是一个 IP 地址,因此我们需要先把域名转换成相应 IP 地址。浏览器会首先从缓存中找是否存在域名&…...
[C++]——带你学习类和对象
类和对象——上 目录:一、面向过程和面向对象二、类的概念三、类的访问限定符和封装3.1 访问限定符3.2 封装 四、类的作用域五、类的实例化六、类的对象大小的计算七、类成员函数this指针7.1 this指针的引用7.2 this 指针的特性 目录: 类和对象是很重要…...
Docker多平台、跨平台编译打包
大多数带有Docker官方标识的镜像都提供了多架构支持。如:busybox镜像支持amd64, arm32v5, arm32v6, arm32v7, arm64v8, i386, ppc64le, and s390x。当你在amd64设备上运行容器时,会拉取amd64镜像。 当你需要构建多平台镜像时,可以用 --platf…...
LLM系列 | 22 : Code Llama实战(下篇):本地部署、量化及GPT-4对比
引言 模型简介 依赖安装 模型inference 代码补全 4-bit版模型 代码填充 指令编码 Code Llama vs ChatGPT vs GPT4 小结 引言 青山隐隐水迢迢,秋尽江南草未凋。 小伙伴们好,我是《小窗幽记机器学习》的小编:卖热干面的小女孩。紧接…...
Nginx的进程结构实例演示
可以参考《Ubuntu 20.04使用源码安装nginx 1.14.0》安装nginx 1.14.0。 nginx.conf文件中worker_processes 2;这条语句表明启动两个worker进程。 sudo /nginx/sbin/nginx -c /nginx/conf/nginx.conf开启nginx。 ps -ef | grep nginx看一下进程情况。 sudo /nginx/sbin/ng…...
【Nginx36】Nginx学习:SSI静态文件服务器端包含模块
Nginx学习:SSI静态文件服务器端包含模块 这个模块让我想到了 2009 年刚刚工作的时候。最早我是做 .NET 的,而第一家公司其实是从 ASP 向 ASP.NET 转型中,因此,还是有不少的 ASP 做的页面。在那个时候,就用到了 SSI 。 …...
StripedFly恶意软件框架感染了100万台Windows和Linux主机
导语 近日,一款名为StripedFly的恶意软件框架在网络安全研究人员的监视之外悄然感染了超过100万台Windows和Linux系统。这款跨平台的恶意软件平台在过去的五年中一直未被察觉。在去年,卡巴斯基实验室发现了这个恶意框架的真实本质,并发现其活…...
蓝桥杯每日一题2023.10.25
乘积尾零 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 由于需要相乘的数很多,所以我们不能直接进行暴力模拟,我们知道10 2 * 5, 所以我们只需要找出这个数2和5的个数,其中2和5个数小的那个则为末尾0出现的个数 #include<bi…...
【C++】详解map和set基本接口及使用
文章目录 一、关联式容器与键值对1.1关联式容器(之前学的都是序列容器)1.2键值对pairmake_pair函数(map在插入的时候会很方便) 1.3树形结构的关联式容器 二、set2.1set的基本介绍2.1默认构造、迭代器区间构造、拷贝构造࿰…...
如何学习 Linux 内核内存管理
Linux内核内存管理部分是Linux内核中第二复杂的部分,但也非常有趣。学习它的最佳方法就是阅读代码。但在不了解术语和当前 mm 部分到底发生了什么的情况下,显然不能随意开始阅读代码。因此,我想这样开始学习比较好: 了解当前的 LS…...
【计算机网络】(谢希仁第八版)第一章课后习题答案
1.计算机网络可以向用户提供哪些服务? 答:例如音频,视频,游戏等,但本质是提供连通性和共享这两个功能。 连通性:计算机网络使上网用户之间可以交换信息,好像这些用户的计算机都可以彼此直接连…...
Operator开发之operator-sdk入门
1 operator-sdk 除了kubebuilder,operator-sdk是另一个常用的用于开发Operator的框架,不过operator-sdk还是基于kubebuilder,因此,通常还是建议使用kubebuilder开发Operator。 2 环境准备 跟kubebuilder类似,需要安…...
RabbitMQ生产者的可靠性
目录 MQ使用时会出现的问题 生产者的可靠性 1、生产者重连 2、生产者确认 3、数据持久化 交换机持久化 队列持久化 消息持久化 LazyQueue懒加载 MQ使用时会出现的问题 发送消息时丢失: 生产者发送消息时连接MQ失败生产者发送消息到达MQ后未找到Exchange生…...
集群节点批量执行 shell 命令
1、SSH 工具本身支持多窗口 比如 MobaXterm: 2、编写脚本通过 ssh 在多台机器批量执行shell命令 创建 ssh_hosts 配置文件,定义需要批量执行的节点(必须能够通过 ssh 免密登录,且存在同名用户) vim ssh_hostsbig…...
fl studio21.2水果软件怎么设置中文?
FL Studio编曲软件真的是个神器,不过一开始打开看到全是英文,有点头大,对吧?其实切换成中文版超级简单,只需要几个步骤就搞定啦!我自己也是用中文版的,觉得用起来更得心应手,效率也提…...
.NET CORE 3.1 集成JWT鉴权和授权2
JWT:全称是JSON Web Token是目前最流行的跨域身份验证、分布式登录、单点登录等解决方案。 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT令牌在api接口中校验用户的身份以确认用户是否有访问api的权限。 授权:这是使用JWT的…...
nbcio-boot如何进行gitee第三方登录
更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H5) : http://122.227.135.243:9888 1、用户g…...
火狐浏览器配置Burp Suite抓包完全指南
1. 为什么火狐浏览器在Burp Suite里“抓不到包”?——不是工具不行,是链路断了很多人第一次用Burp Suite配火狐时,点开Proxy → Intercept is on,浏览器照常访问网站,但Burp的HTTP History里空空如也。刷新十次、重启三…...
独立开发者如何利用Taotoken的Token Plan套餐有效控制月度预算
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者如何利用Taotoken的Token Plan套餐有效控制月度预算 作为一名独立开发者,项目预算通常有限,而AI…...
使用 Node.js 和 Taotoken 为博客网站快速搭建一个智能内容摘要生成接口
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用 Node.js 和 Taotoken 为博客网站快速搭建一个智能内容摘要生成接口 对于个人博客站长而言,为篇幅较长的文章提供一…...
Taotoken 的 Token Plan 套餐如何帮助初创项目更可控地管理大模型调用预算
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken 的 Token Plan 套餐如何帮助初创项目更可控地管理大模型调用预算 对于预算有限的初创团队或个人开发者而言,大…...
破解行业共性管控难题,推动矿山安全体系迭代升级 ——基于视频孪生无感定位的矿山安全体系革新技术方案
破解行业共性管控难题,推动矿山安全体系迭代升级——基于视频孪生无感定位的矿山安全体系革新技术方案一、方案引言国内煤炭矿山长期在人员监管、灾害应急、隐患溯源、空间管控层面沉淀诸多共性难题,佩戴管控流于形式、监测数据失真失实、灾变监测体系快…...
Claude Code 与 AI 创业赚钱指南:从工具到印钞机的完整路径
一个高中生,零编程基础,养了 15 个 AI 员工,月成本不到 400 美元,年收入上万美元。一个独立开发者,花一小时用 AI 搓出 App,上架四小时登顶付费榜,入账 40 万。156 个 AI 创业项目,平…...
Sobolev学习代理加速优化:激活函数与径向基函数选择鲁棒性分析
1. 项目概述与核心思路在工程优化和科学计算领域,我们常常会遇到一个令人头疼的问题:目标函数的每一次评估都极其昂贵。比如,一次评估可能意味着运行一次耗时数小时的流体力学仿真,或者调用一次复杂的有限元分析。传统的无导数优化…...
字典树(Trie)详解 + Java 代码实现
目录 一、字典树核心概念 1. 结构特点 2. 核心应用场景 3. 时间复杂度 二、字典树结构设计 三、完整 Java 代码实现 四、代码逐段讲解 1. 节点类 TrieNode 2. 插入方法 insert 3. 查询单词 search 4. 查询前缀 startsWith 五、字典树优点 vs 缺点 优点 缺点 六、…...
如何用DeepL Chrome翻译插件打破语言障碍:从安装到精通的完整指南
如何用DeepL Chrome翻译插件打破语言障碍:从安装到精通的完整指南 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 你是否经常遇到需要阅读外文网页却苦…...
终极指南:如何用OpenCore Legacy Patcher让旧Mac焕发新生,完美运行最新macOS
终极指南:如何用OpenCore Legacy Patcher让旧Mac焕发新生,完美运行最新macOS 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否拥…...
