最近在写一些字符串函数的优化,用到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/

W​i​n​d​o​w​s​ ​X​6​4​汇​编​入​门​(​1​) | http://wenku.baidu.com/view/3093d52d453610661ed9f4b0.html

Windows x64汇编函数调用约定的更多相关文章

  1. Windows X64汇编入门(1)

    最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助.我也是刚接触这方面知识,文中肯定有错误之处,大家多指正.文章的标题包含了本文的四方面主要内容: ...

  2. X86/X64 函数调用约定

    C 语言有 __cdecl.__stdcall.__fastcall.naked.__pascal. C++ 语言有 __cdecl.__stdcall.__fastcall.naked.__pasc ...

  3. 汇编  cdecl 函数调用约定,stdcall 函数调用约定

    知识点:  cdecl 函数调用约定  stdcall 函数调用约定  CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...

  4. x64汇编第三讲,64位调用约定与函数传参.

    目录 x64汇编第三讲,64位调用约定与函数传参. 一丶复习X86传参 二丶x64汇编 2.1汇编详解 x64汇编第三讲,64位调用约定与函数传参. 一丶复习X86传参 在x86下我们汇编的传参如下: ...

  5. 深入理解Windows X64调试

    随着64位操作系统的普及,都开始大力进军x64,X64下的调试机制也发生了改变,与x86相比,添加了许多自己的新特性,之前学习了Windows x64的调试机制,这里本着“拿来主义”的原则与大家分享. ...

  6. 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)

    0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...

  7. Bypassing PatchGuard on Windows x64

    [说明] 1.  本文是意译,加之本人英文水平有限.windows底层技术属菜鸟级别,本文与原文存在一定误差,请多包涵. 2.  由于内容较多,从word拷贝过来排版就乱了.故你也可以下载附件. 3. ...

  8. x86 x64下调用约定浅析

    x86平台下调用约定 我们都知道x86平台下常用的有三种调用约定,__cdecl.__stdcall.__fastcall.我们分别对这三种调用约定进行分析. __cdecl __cdecl是C/C+ ...

  9. Windows x64 栈帧结构

    0x01 前言 Windows 64位下函数调用约定变为了快速调用约定,前4个参数采用rcx.rdx.r8.r9传递,多余的参数从右向左依次使用堆栈传递.本次文章是对于Windows 64位下函数调用 ...

随机推荐

  1. flask请求异步执行(转载)

    Flask默认是不支持非阻塞IO的,表现为: 当 请求1未完成之前,请求2是需要等待处理状态,效率非常低. 在flask中非阻塞实现可以由2种: 启用flask多线程机制 # Flask from f ...

  2. Kudu系列-基础

    Apache Kudu 支持Insert/Update/Delete 等写操作(Kudu 随机写效率也很高, 实测对一个窄表做全字段update, 其速度达到了Insert速度的88%, 而verti ...

  3. luogu 2878 贪心

    其实这题不难,只是想告诉自己:贪心不全是真的脑残拿最大就AC 此题实际上就是比较x,y优先级利用时间计算得到a[i]t/a[i].d(没错时间在上,并非惯性思维的d在上) t*a[x].d+(t+a[ ...

  4. WebSocket起航 JavaScript客户端和Server通信

    Message  =>JSON  => Move 客户端发给服务器总是Move  server.send(JSON.stringify({row: row, column: column} ...

  5. Linux常用功能及实现命令

    1.设置node.npm.appium等命令全局访问 因为 /opt/node/bin这个目录是不在环境变量中的,所以只能到该目录下才能执行node命令,如果在任意目录下执行node命令的话 ,必须通 ...

  6. python之读写文件

    1. 读取文件数据,文件必须存在才可以读且如要读取的文件不和当前.py在同一个包下,需要特别指定此文件路径才行 f=open('test.txt',encoding='utf-8')#填写文件路径,打 ...

  7. python之字符串常用的方法

    1. 去掉空格或换行符 s='. hello .world .\n' new_s = s.strip()#默认去掉字符串前后的空格和换行符 new_s = s.strip('.')#可传参去掉字符串前 ...

  8. js判断浏览器类型和版本

    原网址:http://www.cnblogs.com/rubylouvre/archive/2009/10/14/1583362.html 除了另无它法,肯定不使用navigator.userAgen ...

  9. 浏览器通知--window.Notification

    参考链接:http://blog.csdn.net/guoquanyou/article/details/51726571 Web Notifications是HTML5 的一个特性,目前我知道的有谷 ...

  10. ES6 基础

    转载自:ES6 基础 一.新的变量声明方式 let/const 与var不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升. 通过2个简单的例子来 ...