rip c语言,GNU C 对标准C语言的扩展
特殊属性声明
GNU C 允许声明函数、变量和类型的特殊属性,以便进行手工的代码优化和定制。如果要指定一个属性声明,只需要在声明后添加__ attribute __((ATTRIBUTE))。其中ATTRIBUTE为属性说明,如果存在多个属性,则以逗号分隔。GNU C 支持noreturn,noinline, always_inline, pure, const, nothrow, format, format_arg, no_instrument_function, section, constructor, destructor, used, unused, deprecated, weak, malloc, alias warn_unused_result nonnull等十个属性。
noreturn属性作用于函数,表示该函数从不返回。这会让编译器优化代码并消除不必要的警告信息。例如: #define ATTRIB_NORET __attribute__((noreturn)) ....
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;
packed属性作用于变量和类型,用于变量或结构域时,表示使用最小可能的对齐,用于枚举、结构或联合类型时表示该类型使用最小的内存。如对于结构体,就是它告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。例如: struct example_struct
{
char a;
int b;
long c;
} __attribute__((packed));
regparm属性用于指定最多可以使用n个寄存器(eax, edx, ecx)传递参数,n的范围是0~3,超过n时则将参数压入栈中(n=0表示不用寄存器传递参数)。
注意:以上这些属性都是在X86处理器体系结构下的,在X64体系结构下,大部分内容都是同样有效的。但是,这里要注意regparm属性,由于在X64体系结构下,GUN C的默认调用约定使用寄存器传递参数。所以,如果regparm属性里使用的寄存器个数超过3个,也仍然会使用其他寄存器来传递参数。这一点要遵循X64体系结构的调用约定。
下面可以看一个例子。 int q = 0x5a;
int t1 = 1;
int t2 = 2;
int t3 = 3;
int t4 = 4;
#define REGPARM3 __attribute((regparm(3)))
#define REGPARM0 __attribute((regparm(0)))
void REGPARM0 p1(int a)
{
q = a + 1;
}
void REGPARM3 p2(int a, int b, int c, int d)
{
q = a + b + c + d + 1;
}
int main()
{
p1(t1);
p2(t1,t2,t3,t4);
return 0;
}
使用objdump命令反汇编,相关命令如下: objdump -D 可执行程序
其中-D选项用于反汇编所有的程序段,包括:代码段、数据段、只读数据段以及一些系统段等等。而-d命令只反汇编代码段的内容。
反汇编后的关键代码如下: Disassembly of section .text:
0000000000400474 :
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: 89 7d fc mov %edi,-0x4(%rbp)
40047b: 8b 45 fc mov -0x4(%rbp),%eax
40047e: 83 c0 01 add $0x1,%eax
400481: 89 05 3d 04 20 00 mov %eax,0x20043d(%rip) # 6008c4
400487: c9 leaveq
400488: c3 retq
0000000000400489 :
400489: 55 push %rbp
40048a: 48 89 e5 mov %rsp,%rbp
40048d: 89 7d fc mov %edi,-0x4(%rbp)
400490: 89 75 f8 mov %esi,-0x8(%rbp)
400493: 89 55 f4 mov %edx,-0xc(%rbp)
400496: 89 4d f0 mov %ecx,-0x10(%rbp)
400499: 8b 45 f8 mov -0x8(%rbp),%eax
40049c: 8b 55 fc mov -0x4(%rbp),%edx
40049f: 8d 04 02 lea (%rdx,%rax,1),%eax
4004a2: 03 45 f4 add -0xc(%rbp),%eax
4004a5: 03 45 f0 add -0x10(%rbp),%eax
4004a8: 83 c0 01 add $0x1,%eax
4004ab: 89 05 13 04 20 00 mov %eax,0x200413(%rip) # 6008c4
4004b1: c9 leaveq
4004b2: c3 retq
00000000004004b3 :
4004b3: 55 push %rbp
4004b4: 48 89 e5 mov %rsp,%rbp
4004b7: 53 push %rbx
4004b8: 8b 05 0a 04 20 00 mov 0x20040a(%rip),%eax # 6008c8
4004be: 89 c7 mov %eax,%edi
4004c0: e8 af ff ff ff callq 400474
4004c5: 8b 0d 09 04 20 00 mov 0x200409(%rip),%ecx # 6008d4
4004cb: 8b 15 ff 03 20 00 mov 0x2003ff(%rip),%edx # 6008d0
4004d1: 8b 1d f5 03 20 00 mov 0x2003f5(%rip),%ebx # 6008cc
4004d7: 8b 05 eb 03 20 00 mov 0x2003eb(%rip),%eax # 6008c8
4004dd: 89 de mov %ebx,%esi
4004df: 89 c7 mov %eax,%edi
4004e1: e8 a3 ff ff ff callq 400489
4004e6: b8 00 00 00 00 mov $0x0,%eax
4004eb: 5b pop %rbx
4004ec: c9 leaveq
4004ed: c3 retq
4004ee: 90 nop
4004ef: 90 nop
Disassembly of section .data:
00000000006008c0 <__data_start>:
6008c0: 00 00 add %al,(%rax)
...
00000000006008c4 :
6008c4: 5a pop %rdx
6008c5: 00 00 add %al,(%rax)
...
00000000006008c8 :
6008c8: 01 00 add %eax,(%rax)
...
00000000006008cc :
6008cc: 02 00 add (%rax),%al
...
00000000006008d0 :
6008d0: 03 00 add (%rax),%eax
...
00000000006008d4 :
6008d4: 04 00 add $0x0,%al
...
如果读者还记得2.2.3节中,关于GCC基于X64体系结构的调用约定的话,那就很容易可以看出,函数p1和p2都使用寄存器传递参数,顺序就是RDI, RSI, RDX, RCX,这些细节已经跟regparm的规定完全不一致了。所以,在这里作者觉得,regparm已经不起作用了。
rip c语言,GNU C 对标准C语言的扩展相关推荐
- GNU C 对标准C语言的扩展(转载 懵懵懂懂)
GNU C 对标准C语言的扩展 为了方便使用,GNU C在标准C语言的基础上进行了部分方便开发的扩展.这里讲解一些开发中可能会用到的,或者使用频率比较高的内容. 1 零长度数组和变量长度数组 GNU ...
- c语言中实型标准,C语言中的基本数据类型--实型数据
C语言里面关于double类型的打印:%lf , %le , %lE e/E是指数形式的,不过e打印的是小写,E打印的是大写. g/G会截断一些小数,比较不精确. %e double Si ...
- linux标准c和c编译器6,linux内核中GNU C和标准C的区别
linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...
- 标准C语言day02
标准C语言day02 复习: 1.常用的Linux命令 ls.cd.pwd clear touch cp mv rm cat/more/head/tail mkdir rmdir chmod find ...
- 标准C语言day03
标准C语言day03 复习: 1.数据类型: signed char 1 %hhd -128~127 signed short 2 %hd -32768~32767 signed int 4 %d 正 ...
- c语言三个标准流文件格式,标准C语言day02
标准C语言day02 复习: 1.常用的Linux命令 ls.cd.pwd clear touch cp mv rm cat/more/head/tail mkdir rmdir chmod find ...
- 基于标准C语言的数字图像处理基本框架(转)
考虑到现有的数字图像处理都是基于Windows平台,都或多或少使用了Win32 API函数,不能移植到Linux或者嵌入式系统中.为了使程序可移植,采用标准C语言建立了数字图像处理的基本框架,如下图所 ...
- 【中级软考】UML图(Unified Modeling Language统一建模语言、标准建模语言)
文章目录 UML图 UML图的作用 主要模型 功能模型 对象模型 动态模型 图的种类 用例图 类图 对象图 包图 活动图 状态图 1.概述: 2.构成要素: 2.1状态(States): 2.2转移( ...
- 独立式环境与宿主式环境————《标准C语言指南》读书笔记01
独立式环境与宿主式环境----<标准C语言指南>读书笔记01 在编写和转换一个C程序之前,需要考虑它的执行环境,因为这关系到源文件的内容(程序应当如何编写),也关系到转换后的程序能否正常执 ...
最新文章
- The system cannot find the file specified
- 数据挖掘(Data Mining)| 数据分析建模理论基础
- 移动端微信页面的一些自己爬的坑
- P2774 方格取数问题
- Android --- Bundle实现数据的读取
- EL函数以及自定义标签的应用
- HiveQL: 数据操作
- 国内一些大公司的开源项目
- Linux操作系统基础解析之(三)——基本命令行操作及获得帮助的方法
- c语言抖动算法,游戏中抖动(振动)算法的实现
- 录屏存储为gif图片
- 网站关键词SEO排名,SEO长尾关键词排名工具
- html 圆圈透明 其他不透明,Javascript HTML5 Canvas绘制透明圆圈
- Passper for PDF v3.6.1.1
- 卷积神经网络(CNN)经典模型分析(一)
- python操作ymal文件之PyYAML库的使用
- Oracle索引梳理系列(五)- Oracle索引种类之表簇索引(cluster index)
- 零工经济爆发:蓝鸟云破而后立,BOSS直聘稳步推进
- vscode缩进和Eslint缩进问题解决
- K临近算法检测异常操作(一)
热门文章
- 前端学习(3063):vue+element今日头条管理-总页码处理2
- [html] HTML5如何使用音频和视频?
- [vue] vue开发过程中你有使用什么辅助工具吗?
- 工作243:name报错
- 前端学习(2216):react元素渲染
- 前端学习(1746):前端调试值之时间监听
- mybatis学习(17):列名与属性名不一致的情况(使用别名)
- spring学习(26):更优雅的依赖注入 在@bean注入参数
- STM32F407控制AD7606 采用HAL库的TIM和SPI
- Qt如何将数据保存成CSV文件