Windows x64汇编函数调用约定
最近在写一些字符串函数的优化,用到x64汇编,我也是第一次接触,故跟大家分享一下。
x86:又名 x32 ,表示 Intel x86 架构,即 Intel 的32位 80386 汇编指令集。
x64:表示 AMD64 和 Intel 的 EM64T ,而不包括 IA64 。至于三者间的区别,可自行搜索。
x64 跟 x86 相比寄存器的变化,如图:

从图上可以看到,X64架构相对于X86架构的主要变化,是将原来所有的寄存器都扩大了一倍,例如EAX现在扩充成RAX,同时,又新增加了从R8~R15这8个64位的寄位器,有点RISC的味道(RISC特点就是寄存器多)。
然后还有下面的一些改变:
- x64上面默认的函数调用约定是 fast call ,也就是 ABI 是 fast call ;
- 一个函数在调用时,前四个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈;
- 调用者负责在栈上分配32字节的“shadow space”,用于存放那四个存放调用参数的寄存器的值(亦即前四个调用参数);
- 小于64位(bit)的参数传递时高位并不填充零(例如只传递ecx),大于64位需要按照地址传递;
- 被调用函数的返回值是整数时,则返回值会被存放于RAX;
- 被调用函数不负责清栈,调用者负责清理栈;
- RAX,RCX,RDX,R8,R9,R10,R11是“易挥发”的,不用特别保护,其余寄存器需要保护。(x86下只有eax, ecx, edx是易挥发的)
- 栈需要16字节对齐,“call”指令会入栈一个8字节的返回值(注:即函数调用前原来的RIP指令寄存器的值),这样一来,栈就对不齐了(因为RCX、RDX、R8、R9四个寄存器刚好是32个字节,是16字节对齐的,现在多出来了8个字节)。所以,所有非叶子结点调用的函数,都必须调整栈RSP的地址为16n+8,来使栈对齐。
- 对于 R8~R15 寄存器,我们可以使用 r8, r8d, r8w, r8b 分别代表 r8 寄存器的64位、低32位、低16位和低8位。
一些其他要注意的小问题:
- 另外一些小问题要注意,AMD64不支持 push 32bit 寄存器的指令,最好的方法就是 push 和 pop 都用64位寄存器,即 push rbx ,不要使用 push ebx 。
- 另外要补充的一点是,在一般情况下,X64 平台的 RBP 栈基指针被废弃掉,只作为普通寄存器来用,所有的栈操作都通过 RSP 指针来完成。
遗留问题
以上都是关于 Windows 上的调用约定,即 Visual Studio 上使用的调用约定,至于 GCC 的函数调用约定是否一致,还不清楚,有知道的请指点一下,我从 asmlib 的64位汇编看,GCC 好像第一个参数用的是 rdi ,而不是 rcx 。
示例:
; 示例代码 1.asm
; 语法:GoASM DATA SECTION
text db 'Hello x64!',
caption db 'My First x64 Application', CODE SECTION
START: sub rsp, 28h ; 堆栈预留 shadow space (40 + 8)字节 xor r9d, r9d ; r9
lea r8, caption ; r8
lea rdx, text ; rdx
xor rcx, rcx ; rcx call MessageBoxA add rsp, 28h ; 调用者自己恢复堆栈 ret
参考文章
Windows平台X64函数调用约定与汇编代码分析 | http://kelvinh.github.io/blog/2013/08/05/windows-x64-calling-conventions/
x64 参数传递 | http://hyperiris.blog.163.com/blog/static/1808400592011715111957863/
Windows X64汇编入门(1) | http://wenku.baidu.com/view/3093d52d453610661ed9f4b0.html
Windows x64汇编函数调用约定的更多相关文章
- Windows X64汇编入门(1)
最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助.我也是刚接触这方面知识,文中肯定有错误之处,大家多指正.文章的标题包含了本文的四方面主要内容: ...
- X86/X64 函数调用约定
C 语言有 __cdecl.__stdcall.__fastcall.naked.__pascal. C++ 语言有 __cdecl.__stdcall.__fastcall.naked.__pasc ...
- 汇编 cdecl 函数调用约定,stdcall 函数调用约定
知识点: cdecl 函数调用约定 stdcall 函数调用约定 CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...
- x64汇编第三讲,64位调用约定与函数传参.
目录 x64汇编第三讲,64位调用约定与函数传参. 一丶复习X86传参 二丶x64汇编 2.1汇编详解 x64汇编第三讲,64位调用约定与函数传参. 一丶复习X86传参 在x86下我们汇编的传参如下: ...
- 深入理解Windows X64调试
随着64位操作系统的普及,都开始大力进军x64,X64下的调试机制也发生了改变,与x86相比,添加了许多自己的新特性,之前学习了Windows x64的调试机制,这里本着“拿来主义”的原则与大家分享. ...
- 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)
0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...
- Bypassing PatchGuard on Windows x64
[说明] 1. 本文是意译,加之本人英文水平有限.windows底层技术属菜鸟级别,本文与原文存在一定误差,请多包涵. 2. 由于内容较多,从word拷贝过来排版就乱了.故你也可以下载附件. 3. ...
- x86 x64下调用约定浅析
x86平台下调用约定 我们都知道x86平台下常用的有三种调用约定,__cdecl.__stdcall.__fastcall.我们分别对这三种调用约定进行分析. __cdecl __cdecl是C/C+ ...
- Windows x64 栈帧结构
0x01 前言 Windows 64位下函数调用约定变为了快速调用约定,前4个参数采用rcx.rdx.r8.r9传递,多余的参数从右向左依次使用堆栈传递.本次文章是对于Windows 64位下函数调用 ...
随机推荐
- putty-psftp
putty-psftp putty文上传下载 open hostname cd directory lcd directory put file get file Example: open 192. ...
- Tips and Tricks for Debugging in chrome
Tips and Tricks for Debugging in chrome Pretty print On sources panel ,clicking on the {} on the bot ...
- 介绍3款Markdown编辑器
为什么写此篇 自从CSDN的博客有了Markdown后,慢慢的了解并学会了用Markdown语法写博客.但CSDN博客是在浏览器中使用,于是一直寻找离线的Markdown编辑器. 网上先是找到了M ...
- 【leetcode-84】 柱状图中最大的矩形
(1pass,比较简单的hard) 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每 ...
- HDU 1050(搬椅子 数学)
题意是在一个有 400 个房间的走廊中搬动房间里的椅子,如果两次的路线重叠,就要分两次搬动,如果不重叠,就可以一次搬动. 开始的时候直接当成求线段重叠条数的题,发现这种思路完全是错的,比如 1 - 3 ...
- Python复习笔记(八)迭代器和生成器和协程
1. 迭代器 1.1 可迭代对象 判断xxx_obj是否可以迭代 在第1步成立的前提下,调用 iter 函数得到 xxx_obj 对象的 __iter__ 方法的返回值 __iter__ 方法的返回值 ...
- SpringBoot常用注解使用
1.RequestBody和ResponseBody注解 @RequestMapping(“url”),这里的 url写的是请求路径的一部分,一般作用在 Controller的方法上,作为请求的映射地 ...
- zookeeper的安装与使用
zookeeper的安装与使用: Zookeeper简介 1.可以作为集群的管理工具使用. 2.可以集中管理配置文件. Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理.命名.分布式 ...
- 网易PM599产品笔试题
前几天做了网易PM599的云计算领域产培生的笔试题目,下面整理了一下各个方向的笔试题和我对这些题目的解答. 云计算领域: 1.对工业互联网的理解,结合自身优势谈谈自己应该怎么去创业. 工业互联网是一次 ...
- js 操作对象 记录
js 对象记录一下: let obj_1 = { name : 'james', age : '22', sex: '1' } for ( i in obj_1 ) { console.log(i) ...