64位汇编第二讲——64位汇编中局部变量使用及抬栈方法29171230

一.纯写64位汇编时局部变量处理和参数寄存器保存位置

纯写64位汇编和用VS2013写64位C代码生成的汇编会有一些格式上的区别,VS2013写64位C代码生成的汇编中是没用到栈基址寄存器rbp的,但是纯写汇编时只要申明了参数和使用了@LOCAL定义的局部变量,就会用到rbp。且看如下例子:1)用C写64位程序空函数生成的汇编代码,

;C代码
void FunTest2()
{
}
;汇编代码
000000013F753290 40 57                push        rdi
000000013F753292 5F                   pop         rdi
000000013F753293 C3                   ret  

2)在*.asm文件中写一个空函数,并且生成可执行文件,然后在X64dbg中查看其汇编代码如下,                               |

;无参无@LOCAL局部变量时的情形,不过会比较少,因为不多时候都会用到@LOCAL局部变量
MyAdd proc
  ret
MyAdd endp

000000013F231000 | C3                   | ret                                     |

;申明了参数的情形
MyAdd proc n1:DWORD, n2:DWORD, n3:DWORD, n4:DWORD, n5:DWORD, n6:DWORD
  ret
MyAdd endp    

000000013F5A1000 | 55                   | push rbp                                |
000000013F5A1001 | 48 8B EC             | mov rbp,rsp                             |
000000013F5A1004 | C9                   | leave                                   |
000000013F5A1005 | C3                   | ret                                     |

;用到@LOCAL定义的局部变量的情形
MyAdd proc ;n1:DWORD, n2:DWORD, n3:DWORD, n4:DWORD, n5:DWORD, n6:DWORD
    LOCAL @n : Qword
  ret
MyAdd endp

000000013FBB1000 | 55                   | push rbp                                |
000000013FBB1001 | 48 8B EC             | mov rbp,rsp                             |
000000013FBB1004 | 48 83 C4 F8          | add rsp,FFFFFFFFFFFFFFF8                |
000000013FBB1008 | C9                   | leave                                   |
000000013FBB1009 | C3                   | ret    

在写汇编代码时,如果用到基址寄存器,则不用每次都计算抬栈的个数,能大大的方便程序员写代码。在上一次课中讲到64位汇编会腾出至少0x28的空间给调用的函数保存参数寄存器,那么腾出来后该如何存放,参数寄存器的值存放抬0x28字节栈的地址处,因为此时用栈基址寄存器很好访问,如下:

其实在64位程序的设计上,如果有第五个或以上的参数,则是要通过栈传参的,同一个函数中所有的call中,在第一个call之前将所有的参数所需栈大小一起抬了,这能减少函数参数的出栈和入栈,从而提高效率。当然,试想我们能不能在call之间还抬栈呢?是不能的,因为只要一抬栈,rsp的值必然会改变,那么call的函数中要保存参数寄存器通过rsp+8寻址就会有偏差了。其实咋一看这样设计会给64位汇编程序开发造成很大的麻烦,因为每添加一个有第五个参数的call时,就要重新修改抬栈的数量,不过细细想来,我们可以用宏来开发,这样就可以直接改宏就可以了,并且在每个call前注释好它单个抬的栈的大小,方便之后统计校对。

另外一个问题是64位汇编中程序中,该不该用LOCAL类型的局部变量的。用LOCAL类型的局部变量的好处是可以直接通过结构体对象点出成员,使用很方便,这也是64位汇编中唯一可以用作结构体对象点成员的方法,在32位汇编中还可用ASSUME,但64位汇编中ASSUME失效。另外,LOCAL类型的局部变量还是自动抬栈和平栈的,其中使用到了rbp,但也因此抬了8字节的栈,改变了rsp,所以此时只能由rbp+10h来替代rsp+8来保存参数寄存器的值。那么除了LOCAL类型的局部变量,还可以用户自己抬栈来充当局部变量,这样做相对于LOCAL类型的局部变量自然麻烦很多,因为老是要算esp的值和静态局部变量总的自己大小,当然也不是不可能,用宏的话会稍微方便一些。

二. 64位汇编和32位汇编中数据类型的区别

64位汇编中地址是64位即8字节的,以前32位汇编中使用的结构体中对应到64位汇编中,个数和代表的含义都不边,只是有的成员的字节数会变化,如涉及到地址的都会由四字节变成八字节,64位汇编中现成可使用的*.inc文件比较少,如果非要用,只能自己写,但可以参考32位汇编中的结构体和宏,宏不需要改,直接拷贝就好,但结构体可以根据VS2013中64位汇编中结构体进行一些类型上的更改,主要是DWORD改QWORD。另外,64位汇编中函数声明方式为extern 函数名:proc,如extern UpdateWindow:proc,包的头文件方式同32位汇编。定义参数个数多余四个的函数时,同32位汇编中定义和申明,头四个参数,在一开始就赋予rcx、rdx、r8、r9的值。

原文地址:https://www.cnblogs.com/DennyChen/p/8151384.html

时间: 2024-10-10 20:21:18

64位汇编第二讲——64位汇编中局部变量使用及抬栈方法29171230的相关文章

32位汇编第二讲,编写窗口程序,加载资源,响应消息,以及调用C库函数

32位汇编第二讲,编写窗口程序,加载资源,响应消息,以及调用C库函数 (如果想看所有代码,请下载课堂资料,里面有所有代码,这里会讲解怎么生成一个窗口程序) 一丶32位汇编编写Windows窗口程序 首先我们知道32位汇编是可以调用Windows API的,那么今天我们就调用windowsAPI来写一个窗口程序 如果你有windows开发知识,那么就很理解了,如果没有,那么跟着我写,跟着步骤去写,那么也可以写出来 首先我们要编写一个窗口程序(使用SDKAPI编写)有几个步骤 1.设计窗口类 2.注

16位汇编语言第二讲系统调用原理,以及各个寄存器详解

昨天已将简单的写了一下汇编代码,并且执行了第一个显示到屏幕的helloworld 问题? helloworld怎么显示出来了. 一丶显卡,显存的概念 1.显示hello就要操作显示器,这是非常原始的,那个时候的程序员,并没有像现在的RGB(红绿蓝)这样的三色真彩色,那个时候就是操作显卡的,定义了一个标准 这个标准就是我们要往固定的地址写入数据,就会显示出来 具体流程 操作显卡 -> 显卡有自己的缓存 -> 把数据写入到显存中, - > 显示数据 (显示到屏幕上) 但是那个时候是没有字的,

汇编--第二讲

中央处理器 CPU 微处理器抽象为以名称存取的寄存器. 主要包含指令执行的运算器和控制器,还有多种寄存器. CPU工作模式 1 实模式 2 保护模式 3 虚拟8086模式 8086/8088的功能结构 模块一.总线接口单元BIU,主要负责读取指令和操作数. 模块二.执行单元EU,主要负责指令译码和执行. 指令的执行周期: 1.取指令 2.解码 3.取操作数 4.执行 5.存储输出操作数 16位寄存器 段寄存器是一种专用寄存器,专门用于存储器寻址.存放逻辑段的起始地址. code segment

陪老婆你学Photoshop第二讲 - 处理掉图中多余的人或物

老婆,这期咱们讲一下另一个实用的PS功能,平时照片中有多余的人或物出现,由于自己拍摄的时候无法保证,所以等咱们出去再玩后回来就可以把多余的人或物P掉,这样就完美的只有你和我了,下面是方法步骤, 1.打开所选取的图,复制一下Ctrl+J     2.选取套索工具或者钢笔工具,用套索工具把要P掉人的轮廓选出来即可.如果用钢笔工具的话,同样也要把想P掉人的轮廓描绘出来,然后路径变选区:CTRL+回车键.套索工具的优点是快,缺点是不准确,在精度上不如钢笔工具     3.用鼠标点击编辑菜单---填充--

16位汇编第六讲汇编指令详解第二讲

16位汇编第六讲汇编指令详解第二讲 1.比较指令 CMP指令 1.CMP指令是将目的操作数减去源操作数,按照定义相应的设置状态标志 2.CMP指令执行的功能与SUB指令(相减指令)一样,但是不同的是CMP指令之根据结果设置标志位 而不修改值 可以操作的指令格式 CMP reg,imm/reg/mem CMP mem,imm/reg 上面是CMP指令的语法,具体的也可以查询帮助文档,inter手册 inter手册查的办法 第一个框代表了CMP指令的所有语法 比如 reg,reg 表示可以比较寄存器

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看)

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看) 昨天,大家可能都看了代码了,不知道昨天有没有在汇编代码的基础上,实现注入计算器. 如果没有,今天则会讲解,不过建议把昨天代码熟悉一遍(课程是紧跟着来的,请不要拉下任何一天,因为今天的知识, 可能就和昨天的知识挂钩,昨天的知识,和前天的挂钩.....,当然你如你懂汇编,不是新手,那么则可以直接往下看) 一丶远程线程注入,和汇编远程注入的区别 昨天的代码,大家可能看了(没看也没有关系,就是远程线程注入的代码,开发角

16位汇编第一讲简介

汇编第一讲 汇编简介 一.什么是汇编 汇编语言他是计算机语言,计算机语言通俗点说就是人类和计算机(也就是CPU)沟通的桥梁,计算机不认识人类的语言,只认得二进制(0和1)但是我们想让你算计完成我们的工作,每次都是0,和1,那样会崩溃的,(老一辈的是这样的)所以后面汇编语言出现了,用一些简单的助记符来替代机器语言(二进制)通用的语言,比如 + - * / 这种助记符, add....汇编语言是和机器语言一一对应的. 二.汇编语言有什么用处好处     1.学好汇编了,你可以理解计算机更为透彻  

32位程序下调用64位函数——进程32位模式与64位模式切换

之前学习的32位进程中调用64位进程函数的知识整理一下,也就是32位模式与64位模式之间的切换. 相关博客:http://www.cnblogs.com/lanrenxinxin/p/4821152.html 这个博客中提到了github上的开源库,我在另一份开源项目中也看到了个库,可以切换32位至64位. 如果对这个功能具体实现比较感兴趣的朋友可以看看下面的内容. 我阅读了源码并进行了注释,算是对这个具体方法的分析和学习. 关键: 1.在x64下的进程,不管是32位或者是64位,实际上都映射了

学习笔记-汇编-两个16位数字相加获得32位数字

使用的是MASM编译 在XP环境下 command内 debug 调试的 啥也不说 上代码!! assume cs:code,ds:data data segment dw 0fa12h,0fdffh data ends code segment start: mov ax,data mov ds,ax ;设置数据段 mov ax,0h ;清零 mov bx,0h ;清零 mov al,ds:[0] ;fa12低位 mov bl,ds:[2] ;fdff低位 add ax,bx ;两个8位数字相