x64汇编第三讲,64位调用约定与函数传参.
x64汇编第三讲,64位调用约定与函数传参.
一丶复习X86传参
在x86下我们汇编的传参如下:
push eax
call xxx
xxx fun proc
push ebp 保存栈底
mov ebp,esp 设置ebp
sub esp,0C0h 开辟局部变量空间
push ebx 保存寄存器环境
push esi
push edi
pop edi 恢复寄存器环境
pop esi
pop ebx
mov esp,ebp 释放局部变量空间
pop ebp 恢复栈底
ret 返回,平展, 如果是 C在外平展 add esp,xxx stdcall 则内部平展 ret 4
看到上面这段代码.我们就应该在脑海中有一个示意图.

我们可以根据上图可以看到.在调用函数的时候做了那些事情.
1.往栈中存放参数
2.将返回地址入栈
3.保存栈底
4.栈内部进行自己的 申请空间 保存环境 以及释放.
二丶x64汇编
2.1汇编详解
在x64下,万变不离其宗.大部分跟x86一样.
如汇编代码为:
sub rsp,0x28
mov r9,1
mov r8,2
mov rdx,3
mov rcx,4
call xxx
add rsp,0x28
1.传参方式
首先说明一下,在X64下,是寄存器传参. 前4个参数分别是 rcx rdx r8 r9进行传参.多余的通过栈传参.从右向左入栈.
2.申请参数预留空间
在x64下,在调用一个函数的时候,会申请一个参数预留空间.用来保存我们的参数.比如以前我们通过push压栈
参数的值.相应的栈就会抬高.其实x64下,一样会申请.只不过这个地方在进函数的时候并没有值.进入函数之后才会将寄存器的值在拷贝到这个栈中.其实就相当于你还是push了.只不过我是外边申请空间,内部进行赋值.
如下:
sub rsp,0x28 //申请的栈空间为0x28,就相当于我们push rcx rdx r8 r9.只不过只是申请.
call xxxx
add rsp,0x28
xxx //函数内部
mov [rsp - 8],rcx
mov [rsp - 0x10],rdx
mov [rsp - 0x18],r8
mov [rsp - 0x20],r9
xxx
如下图:
我们编写一个简单的x64程序.对其反汇编进行查看.

首先开辟我们的参数空间,以及返回地址空间.我们单步一下查看

可以看大开辟了 5*8个字节大小的空间.
然后下方的汇编对其寄存器赋值.进行传参.说明我们只有4个参数.
此时进入Call内部.看下栈.

3.栈按照16字节对齐
现在我们应该明白了.在调用一个函数的时候. 使用 *sub rsp,xxx**进行抬栈,函数内部则进行参数赋值.
其实也是相当于push了参数.只不过它不像x86一样.在里面进行平栈了.而是外面进行平栈了.
那么有个疑问.比如说我们就4个参数. 通过上面来说.我们应该申请 sub rsp,0x20个字节才对.在CALL的时候
x86 x64都是一样的会将返回地址入栈. 那为什么要rsp,0x28.这样的话会多申请一个参数的值哪.
原因是这样的.栈要按照16字节对齐进行申请.
那么还有人会说.按照16字节对齐,那么我们的参数已经是16字节对齐了.比如为我们4个寄存器申请预留空间. rsp,0x20. (4 * 8 = 32 = 16j进制的 0x20)
那为什么还是会申请 rsp,0x28个字节,并且不对齐.
其实是这样的.当我们在 Call函数的时候.返回地址会入栈.如果按照我们之前申请的rsp,0x20个字节的话.那么当
返回地址入栈之后,现在总共抬栈大小是 0x28个字节.并不是16进制对齐. 但是当我们一开始就申请0x28个字节.
当返回地址入栈.那么就是0x28+8 = 0x30个字节. 0x30个字节不是正好跟16字节对齐吗.
所以我们的疑问也就没有了.
所以申请了0x28个字节,其实多出了的8字节是要跟返回地址一样.进行栈对齐使用.
那么申请的这个8字节空间,是没有用的.只是为了对齐使用.
所以x64汇编其实也就搞明白了.
1.在调用函数之前,会申请参数预留空间.(rcx,rdx,r8,r9)
2.函数内部,会将寄存器传参的值(rcx,rdx,r8,r9)保存到我们申请的预留空间中.
上面这两步其实就相当于x86下的 push r9 push r8 push rdx,push rcx
3.调用约定是__fastcall.传参有rcx rdx,平栈是按照c调用约定平栈. 也就是调用者平栈.
x64汇编第三讲,64位调用约定与函数传参.的更多相关文章
- linux 64位调用
linux系统中64位汇编和32位汇编的系统调用主要有以下不同:(1)系统调用号不同.比如x86中sys_write是4,sys_exit是1:而x86_64中sys_write是1, sys_exi ...
- VC与JavaScript交互(三) --- CWebPage类调用javascript函数(给js函数传参,并取得返回值)
①需要一个别人写好的类CWebPage,将其对于的两个文件WebPage.h和WebPage.cpp添加到工程中. ②添加WebBrowser控件,在视图/对话框类的头文件中#include &quo ...
- VC/MFC中通过CWebPage类调用javascript函数(给js函数传参,并取得返回值)
转自:http://www.cnblogs.com/javaexam2/archive/2012/07/14/2632959.html ①需要一个别人写好的类CWebPage,将其对于的两个文件Web ...
- x86 x64下调用约定浅析
x86平台下调用约定 我们都知道x86平台下常用的有三种调用约定,__cdecl.__stdcall.__fastcall.我们分别对这三种调用约定进行分析. __cdecl __cdecl是C/C+ ...
- 【转载】64 位 Windows 内核虚拟地址空间布局(基于 X64 CPU)
原文链接:http://shayi1983.blog.51cto.com/4681835/1734822 本文为原创翻译,原文出处为 http://www.codemachine.com/articl ...
- 64位gcc编译32位汇编
由于使用as和ld来编译链接汇编程序,在使用C库的时候比较麻烦,需要输入比较多的指令,所以使用gcc进行编译链接.由于书中内容是32位汇编程序,但是机器使用的是64位操作系统,自带的gcc也是64位的 ...
- Jarvis OJ- [XMAN]level2/3_x64-Writeup——64位简单栈溢出
两道64位栈溢出,思路和之前的32位溢出基本一致,所以放在一起 在这两道中体现的32位和64位的主要区别在于函数参数传递的方式 在32位程序运行中,函数参数直接压入栈中 调用函数时栈的结构为:调用函数 ...
- java——JNI(例子控制台(64位)清屏
因为java的最底层是jvm,所以单纯的控制台java程序不能感知jvm再下面的操作系统的情况, 可以通过JNI(Java Native Interface)技术实现java后台调用C++/C的dll ...
- vs2010中配置OpenGL以及针对64位系统所遇问题的解决办法
一.下面将对VS2010中配置OpenGL进行简单介绍. 学习OpenGL前的准备工作 第一步,选择一个编译环境 现在Windows系统的主流编译环境有Visual Studio,Broland C+ ...
随机推荐
- 从Hive1.0升级到Hive2.0(删除hive1.x中的元数据, 并不是数据迁移)
软件环境: linux系统: CentOS6.7 Hadoop版本: 2.6.5 zookeeper版本: 3.4.8 主机配置: 一共m1, m2, m3这五部机, 每部主机的用户名都为centos ...
- PHP CURL的几种用法
1.抓取无访问控制文件 <?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://localhost/mytest/ ...
- dubbo之直连提供者
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获 ...
- Sobel算子取代:基于特定点方向的canny边缘检测
前言: Canny边缘检测使用了Sobel算子,计算dx和dy两个方向,对于特定方向的边缘检测,可以作少量修改. 代码: 计算特定方向上的边缘 void CannyOrient( cv::Mat &a ...
- fileupload 上传控件
<div> <asp:FileUpload ID="FileUpload1" runat="server" /> <asp:But ...
- windows 下安装mysql 成功版
mysql 下载地址 http://dev.mysql.com/downloads/ zip版下载 解压到本地 假设文件保存在C:\mysql-5.7.17-winx64 1.以管理员身份运行cmd. ...
- 题解 P3258 【[JLOI2014]松鼠的新家】(From luoguBlog)
唯一能得分的题也被自己搞炸了,好的. 考场上读完题基本认定和lca脱不了干系,想了一会确认是树剖. 那么问题来了,考前一节课刚发现自己之前打的树剖是错的. 而且就算是错的我也没信心考场调出来. 于是打 ...
- Windows数字代码签名的作用和流程
什么是数字代码签名?数字签名代码是一种技术,它使用数字证书来识别软件的发布商和使用hash算法来确保软件的完整性.数字签名使用公共密匙签名书法被创建,它使用两种不同的密匙:公共密匙和私有密匙,我们称其 ...
- HTML 1.1页面js修改文字颜色
昨天的报告页面,想要实现根据不同文字内容改变字体颜色,效果图: 调试了半天出不来效果,最后请教了前端,上代码: <!DOCTYPE html> <html lang="en ...
- linux backtrace()详细使用说明,分析Segmentation fault
linux backtrace()详细使用说明,分析Segmentation fault 在此之前,开发eCos应用程序时,经常碰到程序挂掉后,串口打印输出一大串让人看不懂的数据.今天才明白,原来这些 ...