版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本文格式为Word版,下载可任意编辑——汇编调用C函数汇编调用C函数
从系统引导过程中的汇编程序跳转到系统主函数中,或者在中断处理的汇编代码中跳转到中断处理函数(传闻中的中断上部),这些过程都是从汇编程序跳转到C程序的,其中不成缺少的有:调用商定,参数传递方式,函数调用方式等。由于这些过程都是在系统内核中,所以,我们讲解的是GNUC语言和ATT汇编语言。话不多说,下面让我们逐一介绍。
汇编调用C函数
函数的调用方式
函数的调用方式其实没那么繁杂,根本上就是jmp、call、ret或者他们的变种而已。让我们先看下面的程序。
inttest
inti=0;
i=1+2;
returni;
intmain
test;
return0;
这段程序根本上没有什么难点,很简朴,对吧?唯一要留神的地方是main函数的返回值,这里个人建议大家要使用int类型作为主函数的返回值,而不要使用void,或者其他类型。虽然,在主函数执行到return0之后就跟我们没有什么关系了。但是,有的编译器要求主函数要有个返回值,或者,在某些场合里,系统环境会用到主函数的返回值。考虑到上述理由,要使用int类型作为主函数的返回值,假设处于某个特殊的或者可预料的环境下,那就无所谓了。
说了这么多,反汇编一下这段代码,看看汇编语言是怎么调用test函数的。工具objdump,用于反汇编二进制程序,它有好多参数,可以反汇编出各类想要的信息。
objdump工具命令:
objdump-dtest
下面是反汇编后的片面代码,把相关的系统运行库等一些与上面C程序不相关的代码疏忽掉。经过删减后的反汇编代码如下:
0000000000400474:
400474:55push%rbp
400475:4889e5mov%rsp,%rbp
400478:c745fc00000000movl$0x0,-0x4%rbp
40047f:c745fc03000000movl$0x3,-0x4%rbp
400486:8b45fcmov-0x4%rbp,%eax
400489:c9leaveq
40048a:c3retq
000000000040048b
:
40048b:55push%rbp
40048c:4889e5mov%rsp,%rbp
40048f:b800000000mov$0x0,%eax
400494:e8dbffffffcallq400474
400499:b800000000mov$0x0,%eax
40049e:c9leaveq
40049f:c3retq
大家先看000000000040048b:这一行,这里就是主函数,前面的000000000040048b其实是函数main的地址。一共16个数,16*4=64,对!这就是64位地址宽度啦。
乍一看,有好多个“%”符号,还记得2.2.1节里讲的ATT汇编语法吗?这就是那里面说——引用寄放器的时候要在前面加“%”符号。
还有一些汇编指令的后缀,如:“l”、“q”。“l”的意思是双字(long型),“q”的意思是四字(64位寄放器的后缀就是这个)。
假设您留心查看,是不是会察觉有些寄放器rbp,rsp等,感觉会跟ebp和esp有关系呢?答对了,esp寄放器是32位寄放器,而rsp寄放器是64位寄放器。这是Intel对寄放器的一种向下继承性,从最开头一字节的al,ah,到两字节的ax(16位),四字节的eax(32位),再到八字节的rax(64位),寄放器的长度在不断的扩展,对于相关指令的使用,也从“b”、“l”,“q”,也是不断的向下继承或扩展。
这里有一条指令leaveq,它等效于movq%rbp,%rsp;popq%rbp;
callq400474这句的意思就是跳转到test函数里执行。其实汇编调用C函数就这么简朴,假设把这条callq指令改成jmpq指令也是可以的。这要从call和jmp的识别上说起,call会把在其之后的那条指令的地址压入栈,在上面反汇编后的代码中,就是0000000000400499,然后再跳转到test函数里执行。而jmpq就不会把地址0000000000400499压入栈中。当函数执行完毕,调用retq指令返回的时候,会把栈中的返回地址弹出到rip寄放器中,这样就返回到main函数中持续执行了。
实现jmpq代替callq的伪代码如下所示:
pushq$0x0000000000400499
jmpq400474
对于callq400474这条指令也可以使用retq来实现。它的实现原理是:指令retq会将栈中的返回地址弹出,并放入到rip寄放器中,然后处理器从rip寄放器所指的地址内取指令后持续执行。根据这个原理,可以先将返回地址0000000000400499压入栈中。然后再将test函数的入口地址0000000000400474压入栈中,接着使用retq指令,以调用返回的形式,从main函数“返回”到test函数中。
实现retq代替callq的伪代码如下所示:
pushq$0x0000000000400499
pushq$0x0000000000400474
retq
这些看起来是不是没有想象的那么难?其实把汇编的原理掌管领会了,这些都是可以生动运用的,梦想这段内容能启发读者的灵感~!
调用商定
对于不同的公司,不同的语言以及不同的需求,都是用各自不同的调用商定,而且他们往往差异很大。在IBM兼容机对市场举行洗牌后,微软操作系统和编程工具占据了统治地位,除了微软之外,还有零星的一些公司,以及开源工程GCC,都各自维护着自己的标准。下面是对比流行的几款调用标准,咱们写的大多数程序都出自这个标准之一。
stdcall
1、在举行函数调用的时候,函数的参数是从右向左依次放入栈中的。
如:
intfunction(intfirst,intsecond)
这个函数的参数入栈依次,首先是参数second,然后是参数first。
2、函数的栈平衡操作是由被调用函数执行的,使用的`指令是retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。例如上面的function函数,当我们把function的函数参数压入栈中后,当function函数执行完毕后,由function函数负责将传递给它的参数first和second从栈中弹出来。
3、在函数名的前面用下划线修饰,在函数名的后面由@来修饰,并加上栈需要的字节数。如上面的function函数,会被编译器转换为_function@8。
cdecl
1、在举行函数调用的时候,和stdcall一样,函数的参数是从右向左依次放入栈中的。
2、函数的栈平衡操作是由调用函数执行的,这点是与stdcall不同之处。stdcall使用retnX平衡栈,cdecl那么使用leave、pop、增加栈指针寄放器的数据等方法平衡栈。
3、每一个调用它的函数都包含有清空栈的代码,所以编译产生的可执行文件会比调用stdcall商定产生的文件大。
cdecl是GCC的默认调用商定。但是,GCC在x64位系统环境下,使用寄放器作为函数调用的参数。按照从左向右的依次,头六个整型参数放在寄放器RDI,RSI,RDX,RCX,R8和R9上,同时XMM0到XMM7用来放置浮点变元,返回值保存在RAX中,并且由调用者负责平衡栈。
fastcall
1.函数调用商定规定,函数的参数在可能的处境下使用寄放器传递参数,通常是前两个DWORD类型的参数或较小的参数使用ECX和EDX寄放器传递,其余参数按照从右向左的依次入栈。
2、函数的栈平衡操作是由被调用函数在返回之前负责除掉栈中的参数。
还有好多调用规矩,如:thiscall、nakedcall、pascal等,有兴趣的读者可以自己去研究一下。
参数传递方式
函数参数的传递方式无外乎两种,一种是通过寄放器传递,另一种是通过内存传递。这两种传递方式在我们平日的开发中并不会被关注,由于不在特殊处境下,这两种传递方式,都可以得志要求。但是,我们要写的是操作系统,在操作系统里面有好多苛刻的环境要求,这使得我们不得不了解这些参数传递方式,来解决这些问题。
寄放器传递
寄放器传递就是将函数的参数放到寄放器里传递,而不是放到栈里传递。这样的好处主要是执行速度快,编译后生成的代码量少。但只有少片面调用规定默认是通过寄放器传递参数,大片面编译器是需要特殊指定使用寄放器传递参数的。
在X86体系布局下,系统调用一般会使用寄放器传递,由于看过的内核种类有限,也不能确定全体的内核都是这么处理的,但是Linux内核断定是这么做的。由于应用程序的执行空间和系统内核的执行空间是不一样的,假设想从应用层把参数传递到内核层的话,最便当快捷的方法是通过寄放器传递参数,否那么需要使用很大的周折才能把数据传递过去,理由会在以后的章节中细致陈述。
内存传递
内存传递参数很好理解,在大多数处境下参数传递都是通过内存入栈的形式实现的。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年实验室室内质控培训课件
- 2026 年粮食生产来之不易科普教育课件
- 2026 年怀揣青春理想奋力逐梦前行课件
- 2026 年端午香囊习俗传统医药小知识课件
- 医院感染防控知识全员考核试题及答案
- mmdx考试拔高试题及答案讲解
- 原液准备浸渍操作工风险评估与管理考核试卷含答案
- 影视评论重要试题和全解答案
- 自控仪表测验题及详细答案
- 农机修理工达标强化考核试卷含答案
- CJT233-2016 建筑小区排水用塑料检查井
- 医院护理人文关怀实践规范专家共识
- 《新实用汉语课本》课件2
- 《我是什么》 省赛获奖
- 厦门百路达高新材料有限公司高纯无氧铜、磷脱氧铜生产项目环境影响报告书
- 新任职科级干部能力提升培训班研讨发言材料心得体会6篇
- 0-3岁婴幼儿认知发展与教育PPT完整全套教学课件
- 谜语知识讲解(优秀教学课件)-人教版
- 功能高分子课件第一章
- (中职)电工技术基础与技能(第2版)项目五 磁场及电磁感应的认知电子课件()
- NB/T 10731-2021煤矿井下防水密闭墙设计施工及验收规范
评论
0/150
提交评论